From fe7988b43353074569c56c74e6dd6f10c4f77cc4 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Thu, 10 Apr 2025 13:03:12 -0500 Subject: [PATCH 01/54] feat(docs): data viz base structure --- .../sidebar/SidebarNavigation.tsx | 15 ++- packages/paste-website/src/constants.ts | 1 + .../engineering/base-chart.mdx | 112 ++++++++++++++++++ .../data-visualization/engineering/index.mdx | 112 ++++++++++++++++++ .../foundations/data-visualization/index.mdx | 10 ++ 5 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 packages/paste-website/src/pages/foundations/data-visualization/engineering/base-chart.mdx create mode 100644 packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index 3c5dc6565d..21264257cd 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -135,9 +135,18 @@ const SiteSidebarNavigation = (): JSX.Element => { Word list - - Data visualization - + + Overview + + Overview + + Base Chart + + + diff --git a/packages/paste-website/src/constants.ts b/packages/paste-website/src/constants.ts index faf02fb74f..96caa18a22 100644 --- a/packages/paste-website/src/constants.ts +++ b/packages/paste-website/src/constants.ts @@ -48,6 +48,7 @@ export const SidebarCategoryRoutes = { FOUNDATIONS: "/foundations", CONTENT: "/foundations/content", FOUNDATIONS_LOCALIZATION: "/foundations/localization", + DATA_VISUALIZATION: "/foundations/data-visualization", PATTERNS: "/patterns", EXPERIENCES: "/experiences", COMPONENTS: "/components", diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/base-chart.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/base-chart.mdx new file mode 100644 index 0000000000..d22c506bc2 --- /dev/null +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/base-chart.mdx @@ -0,0 +1,112 @@ +export const meta = { + title: "Data Visualization - Base Chart", + description: "The base component required to funciton with Paste components.", + slug: "/foundations/data-visualization/engineering/base-chart", +}; + +import Image from "next/image"; +import Highcharts from "highcharts"; +import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; +import HighchartsReact from "highcharts-react-official"; +import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library"; + +import { Box } from "@twilio-paste/box"; +import { Heading } from "@twilio-paste/heading"; +import { Text } from "@twilio-paste/text"; +import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; +import { PageHeaderSeparator } from "@twilio-paste/page-header"; +import { Separator } from "@twilio-paste/separator"; + +import { SidebarCategoryRoutes } from "../../../../constants"; +import DefaultLayout from "../../../../layouts/DefaultLayout"; +import { getNavigationData } from "../../../../utils/api"; + +export default DefaultLayout; + +export const getStaticProps = async () => { + const navigationData = await getNavigationData(); + return { + props: { + navigationData, + }, + }; +}; + + + + + + + + + + + + + +## Introduction + +This foundation page was created to help establish a familiar and accessible user experience when interacting with data visualization across all Twilio products. These recommendations should enable you to tell accurate and convincing stories around data in a visually consistent and accessible manner. + +### Adding Highcharts Accessibility module + +Highcharts by default does not include its [Accessibility](https://www.highcharts.com/docs/accessibility/accessibility-module) module. Every Highcharts license includes the Accessibility module which adheres to the WCAG 2.1 standard and adds enhanced keyboard navigation and screen reader functionality. + +A helper function `applyPasteHighchartsModules` is available from the [data visualization library package](/core/libraries/data-visualization#applypastehighchartsmodules), which applies additional modules to Highcharts. This function should be called at the component level where the Highcharts namespace is passed to HighchartsReact. + +```jsx +import * as Highcharts from "highcharts"; +import HighchartsReact from "highcharts-react-official"; +import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; +import * as React from "react"; +import { + usePasteHighchartsTheme, + applyPasteHighchartsModules, +} from "@twilio-paste/core/data-visualization-library"; +import { ChartContext } from "@twilio-paste/core/chart-provider"; +import { Box } from "@twilio-paste/core/box"; + + +const Chart: React.FC = () => { + applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); + const chartRef = React.useRef(null); + const { options, setChart, setChartRef } = React.useContext(); + const [chartOptions, setChartOptions] = React.useState( + usePasteHighchartsTheme(options) + ); + + React.useLayoutEffect(() => { + setChartOptions(Highcharts.merge(chartOptions, options)); + }, [options]); + + React.useEffect(() => { + if (chartRef.current) { + setChartRef(chartRef.current); + } + }, [chartRef.current]); + + const callback = (chart: Highcharts.Chart) => { + if (chart?.series?.length > 0) { + setChart(chart); + } + }; + + return ( + + + + ); +}; + +export const BaseChart = React.memo(Chart); +``` + + + + diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx new file mode 100644 index 0000000000..08216afd42 --- /dev/null +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -0,0 +1,112 @@ +export const meta = { + title: "Data Visualization", + description: "An introduciton to building charts for engineers.", + slug: "/foundations/data-visualization/engineering/", +}; + +import Image from "next/image"; +import Highcharts from "highcharts"; +import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; +import HighchartsReact from "highcharts-react-official"; +import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library"; + +import { Box } from "@twilio-paste/box"; +import { Heading } from "@twilio-paste/heading"; +import { Text } from "@twilio-paste/text"; +import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; +import { PageHeaderSeparator } from "@twilio-paste/page-header"; +import { Separator } from "@twilio-paste/separator"; + +import { SidebarCategoryRoutes } from "../../../../constants"; +import DefaultLayout from "../../../../layouts/DefaultLayout"; +import { getNavigationData } from "../../../../utils/api"; + +export default DefaultLayout; + +export const getStaticProps = async () => { + const navigationData = await getNavigationData(); + return { + props: { + navigationData, + }, + }; +}; + + + + + + + + + + + + + +## Introduction + +This foundation page was created to help establish a familiar and accessible user experience when interacting with data visualization across all Twilio products. These recommendations should enable you to tell accurate and convincing stories around data in a visually consistent and accessible manner. + +### Adding Highcharts Accessibility module + +Highcharts by default does not include its [Accessibility](https://www.highcharts.com/docs/accessibility/accessibility-module) module. Every Highcharts license includes the Accessibility module which adheres to the WCAG 2.1 standard and adds enhanced keyboard navigation and screen reader functionality. + +A helper function `applyPasteHighchartsModules` is available from the [data visualization library package](/core/libraries/data-visualization#applypastehighchartsmodules), which applies additional modules to Highcharts. This function should be called at the component level where the Highcharts namespace is passed to HighchartsReact. + +```jsx +import * as Highcharts from "highcharts"; +import HighchartsReact from "highcharts-react-official"; +import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; +import * as React from "react"; +import { + usePasteHighchartsTheme, + applyPasteHighchartsModules, +} from "@twilio-paste/core/data-visualization-library"; +import { ChartContext } from "@twilio-paste/core/chart-provider"; +import { Box } from "@twilio-paste/core/box"; + + +const Chart: React.FC = () => { + applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); + const chartRef = React.useRef(null); + const { options, setChart, setChartRef } = React.useContext(); + const [chartOptions, setChartOptions] = React.useState( + usePasteHighchartsTheme(options) + ); + + React.useLayoutEffect(() => { + setChartOptions(Highcharts.merge(chartOptions, options)); + }, [options]); + + React.useEffect(() => { + if (chartRef.current) { + setChartRef(chartRef.current); + } + }, [chartRef.current]); + + const callback = (chart: Highcharts.Chart) => { + if (chart?.series?.length > 0) { + setChart(chart); + } + }; + + return ( + + + + ); +}; + +export const BaseChart = React.memo(Chart); +``` + + + + diff --git a/packages/paste-website/src/pages/foundations/data-visualization/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/index.mdx index bb542d3552..1cfa7b47ca 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/index.mdx @@ -16,6 +16,7 @@ import { Text } from "@twilio-paste/text"; import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; import { PageHeaderSeparator } from "@twilio-paste/page-header"; import { Separator } from "@twilio-paste/separator"; +import {Anchor} from "@twilio-paste/anchor"; import { ResponsiveImage } from "../../../components/ResponsiveImage"; import { SidebarCategoryRoutes } from "../../../constants"; @@ -62,6 +63,15 @@ This foundation page was created to help establish a familiar and accessible use ### For engineers + + + Paste Chart support + + We're actively working on full charting support through a suite of Paste components designed to make it easy to build pre-styled, interactive charts. As we expand these capabilities, we’ll continue adding more examples and documentation in the Engineering section. We plan to roll out support for additional chart types over time and recommend using our components if they fit your current needs. + + + + The easiest way to use the data visualization tokens in your charts is to use `usePasteHighchartsTheme` from the [data visualization library package](/core/libraries/data-visualization) with [Highcharts](https://www.highcharts.com/). The `usePasteHighchartsTheme` hook takes an object of Highchart configurations and returns a new object with Paste colors and fonts. Be sure to include the [Highcharts Accessibility module](/foundations/data-visualization#adding-highcharts-accessibility-module) to ensure that your charts are accessible to all users. From 4654b80f84cb9547f190f50fb052cd303426bc81 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Fri, 11 Apr 2025 09:53:45 -0500 Subject: [PATCH 02/54] feat(data-viz): wokring base chart --- .../components/list/stories/index.stories.tsx | 42 +++++++++++++++- .../stories/base-chart.stories.tsx | 30 ++++++++++++ .../stories/components/BaseChart.tsx | 48 +++++++++++++++++++ .../data-visualization/engineering/index.mdx | 24 +++------- 4 files changed, 126 insertions(+), 18 deletions(-) create mode 100644 packages/paste-libraries/data-visualization/stories/base-chart.stories.tsx create mode 100644 packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx diff --git a/packages/paste-core/components/list/stories/index.stories.tsx b/packages/paste-core/components/list/stories/index.stories.tsx index d48d50dc83..225674ba0a 100644 --- a/packages/paste-core/components/list/stories/index.stories.tsx +++ b/packages/paste-core/components/list/stories/index.stories.tsx @@ -5,7 +5,7 @@ import { Stack } from "@twilio-paste/stack"; import { useTheme } from "@twilio-paste/theme"; import * as React from "react"; -import { ListItem, OrderedList, UnorderedList } from "../src"; +import { List, ListItem, OrderedList, UnorderedList } from "../src"; // eslint-disable-next-line import/no-default-export export default { @@ -110,6 +110,46 @@ export const NestedUnorderedList = (): React.ReactNode => { ); }; +export const DefaultList = (): React.ReactNode => { + return ( + <> + + + Deliver critical time-sensitive messages to employees and customers at scale with the Programmable Messaging + API. + + + + Deliver critical time-sensitive messages to employees and customers at scale with the Programmable Messaging + API. + + + + Deliver critical time-sensitive messages to employees and customers at scale with the Programmable + Messaging API. + + + Proactively inform customers about account activity, purchase confirmations, and shipping notifications + with the + Programmable Messaging API. + + + + Proactively inform customers about account activity, purchase confirmations, and shipping notifications with + the + Programmable Messaging API. + + + + Proactively inform customers about account activity, purchase confirmations, and shipping notifications with + the + Programmable Messaging API. + + + + ); +}; + export const CustomOrderedList: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( diff --git a/packages/paste-libraries/data-visualization/stories/base-chart.stories.tsx b/packages/paste-libraries/data-visualization/stories/base-chart.stories.tsx new file mode 100644 index 0000000000..a1ddbdda1f --- /dev/null +++ b/packages/paste-libraries/data-visualization/stories/base-chart.stories.tsx @@ -0,0 +1,30 @@ +import type { Meta, StoryFn } from "@storybook/react"; +import { Stack } from "@twilio-paste/stack"; +import * as React from "react"; +/* eslint-enable */ + +import { ChartProvider } from "@twilio-paste/chart-provider"; +import { BaseChart } from "./components/BaseChart"; +import { lineChartOptions } from "./options/lineChartOptions"; + +// eslint-disable-next-line import/no-default-export +export default { + title: "Libraries/data-visualization/base-chart", + parameters: { + chromatic: { disableSnapshot: true }, + a11y: { + // no need to a11y check composition of a11y checked components + disable: true, + }, + }, +} as Meta; + +export const HighchartsOptions: StoryFn = () => { + return ( + + + + + + ); +}; diff --git a/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx b/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx new file mode 100644 index 0000000000..517b5bb5bc --- /dev/null +++ b/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx @@ -0,0 +1,48 @@ +import { Box } from "@twilio-paste/box"; +import { ChartContext } from "@twilio-paste/chart-provider"; +import * as Highcharts from "highcharts"; +import HighchartsReact from "highcharts-react-official"; +import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; +import * as React from "react"; + +import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "../../src"; + +const Chart: React.FC = () => { + applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); + const chartRef = React.useRef(null); + const { options, setChart, setChartRef } = React.useContext(ChartContext); + const [chartOptions, setChartOptions] = React.useState( + // disabling animation for stories only. Not included in our docs exmaples + usePasteHighchartsTheme({ ...options, plotOptions: { series: { animation: false } } }), + ); + + React.useLayoutEffect(() => { + setChartOptions(Highcharts.merge(chartOptions, options)); + }, [options]); + + React.useEffect(() => { + if (chartRef.current) { + setChartRef(chartRef.current); + } + }, [chartRef.current]); + + const callback = (chart: Highcharts.Chart) => { + if (chart?.series?.length > 0) { + setChart(chart); + } + }; + + return ( + + + + ); +}; + +export const BaseChart = React.memo(Chart); diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index 08216afd42..a2bfb348b0 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -46,34 +46,24 @@ export const getStaticProps = async () => { ## Introduction -This foundation page was created to help establish a familiar and accessible user experience when interacting with data visualization across all Twilio products. These recommendations should enable you to tell accurate and convincing stories around data in a visually consistent and accessible manner. +When building -### Adding Highcharts Accessibility module - -Highcharts by default does not include its [Accessibility](https://www.highcharts.com/docs/accessibility/accessibility-module) module. Every Highcharts license includes the Accessibility module which adheres to the WCAG 2.1 standard and adds enhanced keyboard navigation and screen reader functionality. - -A helper function `applyPasteHighchartsModules` is available from the [data visualization library package](/core/libraries/data-visualization#applypastehighchartsmodules), which applies additional modules to Highcharts. This function should be called at the component level where the Highcharts namespace is passed to HighchartsReact. +## Base chart ```jsx +import { ChartContext } from "@twilio-paste/core/chart-provider"; +import { Box } from "@twilio-paste/core/box"; +import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "@twilio-paste/core/data-visualization-library"; import * as Highcharts from "highcharts"; import HighchartsReact from "highcharts-react-official"; import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; import * as React from "react"; -import { - usePasteHighchartsTheme, - applyPasteHighchartsModules, -} from "@twilio-paste/core/data-visualization-library"; -import { ChartContext } from "@twilio-paste/core/chart-provider"; -import { Box } from "@twilio-paste/core/box"; - const Chart: React.FC = () => { applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); const chartRef = React.useRef(null); - const { options, setChart, setChartRef } = React.useContext(); - const [chartOptions, setChartOptions] = React.useState( - usePasteHighchartsTheme(options) - ); + const { options, setChart, setChartRef } = React.useContext(ChartContext); + const [chartOptions, setChartOptions] = React.useState(usePasteHighchartsTheme(options)); React.useLayoutEffect(() => { setChartOptions(Highcharts.merge(chartOptions, options)); From 0cbd203d6075b5929e2048c0b75084eb7ec3b2b9 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Fri, 11 Apr 2025 10:37:37 -0500 Subject: [PATCH 03/54] feat(data-viz): wip --- .../src/usePasteHighchartsTheme.tsx | 8 +- .../stories/components/BaseChart.tsx | 2 +- .../sidebar/SidebarNavigation.tsx | 3 - .../engineering/base-chart.mdx | 112 ------------------ .../data-visualization/engineering/index.mdx | 36 +++++- 5 files changed, 42 insertions(+), 119 deletions(-) delete mode 100644 packages/paste-website/src/pages/foundations/data-visualization/engineering/base-chart.mdx diff --git a/packages/paste-libraries/data-visualization/src/usePasteHighchartsTheme.tsx b/packages/paste-libraries/data-visualization/src/usePasteHighchartsTheme.tsx index 23e81c5079..c671813e3a 100644 --- a/packages/paste-libraries/data-visualization/src/usePasteHighchartsTheme.tsx +++ b/packages/paste-libraries/data-visualization/src/usePasteHighchartsTheme.tsx @@ -105,9 +105,15 @@ export const usePasteHighchartsTheme = (options: Highcharts.Options): Highcharts }, }, tooltip: { - backgroundColor: context.backgroundColors.colorBackground, + backgroundColor: context.backgroundColors.colorBackgroundBodyInverse, + borderColor: context.borderColors.colorBorderInverse, + borderWidth: context.borderWidths.borderWidth10, + borderRadius: context.radii.borderRadius30.replace("px", ""), + padding: 12, style: { + fontFamily: context.fonts.fontFamilyText, color: context.textColors.colorText, + fontSize: context.fontSizes.fontSize30, }, }, credits: { diff --git a/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx b/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx index 517b5bb5bc..c0e533d9c3 100644 --- a/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx +++ b/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx @@ -12,7 +12,7 @@ const Chart: React.FC = () => { const chartRef = React.useRef(null); const { options, setChart, setChartRef } = React.useContext(ChartContext); const [chartOptions, setChartOptions] = React.useState( - // disabling animation for stories only. Not included in our docs exmaples + // disabling animation for stories only. Not included in our docs examples usePasteHighchartsTheme({ ...options, plotOptions: { series: { animation: false } } }), ); diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index 21264257cd..844353576a 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -142,9 +142,6 @@ const SiteSidebarNavigation = (): JSX.Element => { categoryRoute={`${SidebarCategoryRoutes.DATA_VISUALIZATION}/engineering`} > Overview - - Base Chart - { - const navigationData = await getNavigationData(); - return { - props: { - navigationData, - }, - }; -}; - - - - - - - - - - - - - -## Introduction - -This foundation page was created to help establish a familiar and accessible user experience when interacting with data visualization across all Twilio products. These recommendations should enable you to tell accurate and convincing stories around data in a visually consistent and accessible manner. - -### Adding Highcharts Accessibility module - -Highcharts by default does not include its [Accessibility](https://www.highcharts.com/docs/accessibility/accessibility-module) module. Every Highcharts license includes the Accessibility module which adheres to the WCAG 2.1 standard and adds enhanced keyboard navigation and screen reader functionality. - -A helper function `applyPasteHighchartsModules` is available from the [data visualization library package](/core/libraries/data-visualization#applypastehighchartsmodules), which applies additional modules to Highcharts. This function should be called at the component level where the Highcharts namespace is passed to HighchartsReact. - -```jsx -import * as Highcharts from "highcharts"; -import HighchartsReact from "highcharts-react-official"; -import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; -import * as React from "react"; -import { - usePasteHighchartsTheme, - applyPasteHighchartsModules, -} from "@twilio-paste/core/data-visualization-library"; -import { ChartContext } from "@twilio-paste/core/chart-provider"; -import { Box } from "@twilio-paste/core/box"; - - -const Chart: React.FC = () => { - applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); - const chartRef = React.useRef(null); - const { options, setChart, setChartRef } = React.useContext(); - const [chartOptions, setChartOptions] = React.useState( - usePasteHighchartsTheme(options) - ); - - React.useLayoutEffect(() => { - setChartOptions(Highcharts.merge(chartOptions, options)); - }, [options]); - - React.useEffect(() => { - if (chartRef.current) { - setChartRef(chartRef.current); - } - }, [chartRef.current]); - - const callback = (chart: Highcharts.Chart) => { - if (chart?.series?.length > 0) { - setChart(chart); - } - }; - - return ( - - - - ); -}; - -export const BaseChart = React.memo(Chart); -``` - - - - diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index a2bfb348b0..4a498c1f99 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -16,6 +16,7 @@ import { Text } from "@twilio-paste/text"; import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; import { PageHeaderSeparator } from "@twilio-paste/page-header"; import { Separator } from "@twilio-paste/separator"; +import { InlineCode } from "@twilio-paste/inline-code"; import { SidebarCategoryRoutes } from "../../../../constants"; import DefaultLayout from "../../../../layouts/DefaultLayout"; @@ -46,9 +47,38 @@ export const getStaticProps = async () => { ## Introduction -When building + + + In progress + As our current data visualization offerings are in progress these documents are subject to change. We will revise and expand these pages when new features are supported. + + -## Base chart +Our charting components are designed to work seamlessly with Highcharts. However, due to licensing restrictions, we cannot include Highcharts directly in our library. This limitation creates challenges when developing components for a library we cannot directly integrate with. + +To address this, we have created components and wrappers that simplify the Highcharts API. These tools expose various props, allowing you to configure charts through a streamlined and user-friendly interface. The props are transformed into objects that Highcharts can interpret, and our components automatically apply styles to the charts for a consistent appearance. + +## Setup + +To ensure our components function correctly, some initial configuration is required in your project. This seciton will cover: +- Storing and retrieving rendered chart objects. +- Setting up the chart context. +- Adding any additional modules required for additional functionality such as gauges, exporting etc. + +### Base chart + +You will need to include a component that retrieves the chart configuration from our components' context and passes it to Highcharts. This component must also capture the rendered chart and store it in our `ChartContext`. + +Storing the rendered chart is essential for several reasons. It allows us to determine the positioning of elements relative to the screen, enabling the placement of components like tooltips. Additionally, it facilitates triggering update functions on the chart for interactions such as zooming or toggling the visibility of series through a legend component. + + + + Modules subject to change + As we expand our supported charts you will need to maintain this file to include any required modules for the new charts or functionality of our components to work correctly. The change will look like the following: + applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); + applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule, HighchartsSankeyModule, ...); + + ```jsx import { ChartContext } from "@twilio-paste/core/chart-provider"; @@ -60,6 +90,7 @@ import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; import * as React from "react"; const Chart: React.FC = () => { + // Load the accessibility module and any other modules you need. applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); const chartRef = React.useRef(null); const { options, setChart, setChartRef } = React.useContext(ChartContext); @@ -76,6 +107,7 @@ const Chart: React.FC = () => { }, [chartRef.current]); const callback = (chart: Highcharts.Chart) => { + // Ensure the chart has been rendered before setting it. This will cause issues in our components if the series is empty. if (chart?.series?.length > 0) { setChart(chart); } From 97f8ac222d8a1dc98e82f604a8c9e73c8a3bd6e6 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Fri, 11 Apr 2025 16:18:19 -0500 Subject: [PATCH 04/54] feat(data-viz): wip --- .../sidebar/SidebarNavigation.tsx | 26 ++++++++ .../data-visualization/chart-provider/api.mdx | 61 +++++++++++++++++++ .../chart-provider/changelog.mdx | 36 +++++++++++ .../chart-provider/index.mdx | 58 ++++++++++++++++++ .../engineering/chart-types.mdx | 57 +++++++++++++++++ .../data-visualization/engineering/index.mdx | 22 +++++-- 6 files changed, 255 insertions(+), 5 deletions(-) create mode 100644 packages/paste-website/src/pages/components/data-visualization/chart-provider/api.mdx create mode 100644 packages/paste-website/src/pages/components/data-visualization/chart-provider/changelog.mdx create mode 100644 packages/paste-website/src/pages/components/data-visualization/chart-provider/index.mdx create mode 100644 packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index 844353576a..84d6d8e2c7 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -142,6 +142,9 @@ const SiteSidebarNavigation = (): JSX.Element => { categoryRoute={`${SidebarCategoryRoutes.DATA_VISUALIZATION}/engineering`} > Overview + + Chart types + { if (name === "Sidebar Navigation") { return null; } + if (name === "Data Visualization") { + return ( + + event({ + category: "Left Navigation", + action: `click-${name}`, + label: name, + }) + } + > + + Chart Provider + + + ); + } return ( {name} diff --git a/packages/paste-website/src/pages/components/data-visualization/chart-provider/api.mdx b/packages/paste-website/src/pages/components/data-visualization/chart-provider/api.mdx new file mode 100644 index 0000000000..87f5279e8f --- /dev/null +++ b/packages/paste-website/src/pages/components/data-visualization/chart-provider/api.mdx @@ -0,0 +1,61 @@ +import Changelog from '@twilio-paste/chart-provider/CHANGELOG.md'; // I don't know why this is needed but if you remove it the page fails to render +import packageJson from '@twilio-paste/chart-provider/package.json'; + +import {SidebarCategoryRoutes} from '../../../../constants'; +import ComponentPageLayout from '../../../../layouts/ComponentPageLayout'; +import {getFeature, getNavigationData, getComponentApi} from '../../../../utils/api'; + +export const meta = { + title: 'ChartProvider', + package: '@twilio-paste/chart-provider', + description: packageJson.description, + slug: '/components/chart-provider/api', +}; + +export default ComponentPageLayout; + +export const getStaticProps = async () => { + const navigationData = await getNavigationData(); + const feature = await getFeature('Chart Provider'); + const {componentApi, componentApiTocData} = getComponentApi('@twilio-paste/chart-provider'); + return { + props: { + data: { + ...packageJson, + ...feature, + }, + componentApi, + mdxHeadings: [...mdxHeadings, ...componentApiTocData], + navigationData, + pageHeaderData: { + categoryRoute: SidebarCategoryRoutes.COMPONENTS, + githubUrl: 'https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/chart-provider', + storybookUrl: '/?path=/story/components-chartprovider', + }, + }, + }; +}; + +## Installation + +```bash +yarn add @twilio-paste/chart-provider - or - yarn add @twilio-paste/core +``` + +## Usage + +```jsx +import { ChartProvider } from '@twilio-paste/core/chart-provider'; + +const ChartProviderExample = () => { + return ( + + + + ); +}; +``` + +## Props + + diff --git a/packages/paste-website/src/pages/components/data-visualization/chart-provider/changelog.mdx b/packages/paste-website/src/pages/components/data-visualization/chart-provider/changelog.mdx new file mode 100644 index 0000000000..829b22e20c --- /dev/null +++ b/packages/paste-website/src/pages/components/data-visualization/chart-provider/changelog.mdx @@ -0,0 +1,36 @@ +import {SidebarCategoryRoutes} from '../../../../constants'; +import Changelog from '@twilio-paste/chart-provider/CHANGELOG.md'; +import packageJson from '@twilio-paste/chart-provider/package.json'; +import ComponentPageLayout from '../../../../layouts/ComponentPageLayout'; +import {getFeature, getNavigationData} from '../../../../utils/api'; + +export const meta = { + title: 'Chart Provider', + package: '@twilio-paste/chart-provider', + description: packageJson.description, + slug: '/components/chart-provider/changelog', +}; + +export default ComponentPageLayout; + +export const getStaticProps = async () => { + const navigationData = await getNavigationData(); + const feature = await getFeature('Chart Provider'); + return { + props: { + data: { + ...packageJson, + ...feature, + }, + navigationData, + mdxHeadings, + pageHeaderData: { + categoryRoute: SidebarCategoryRoutes.COMPONENTS, + githubUrl: 'https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/chart-provider', + storybookUrl: '/?path=/story/components-chartprovider', + }, + }, + }; +}; + + diff --git a/packages/paste-website/src/pages/components/data-visualization/chart-provider/index.mdx b/packages/paste-website/src/pages/components/data-visualization/chart-provider/index.mdx new file mode 100644 index 0000000000..2d2741f82b --- /dev/null +++ b/packages/paste-website/src/pages/components/data-visualization/chart-provider/index.mdx @@ -0,0 +1,58 @@ +import { ChartProvider } from '@twilio-paste/chart-provider'; +import packageJson from '@twilio-paste/chart-provider/package.json'; + +import {SidebarCategoryRoutes} from '../../../../constants'; +import ComponentPageLayout from '../../../../layouts/ComponentPageLayout'; +import {getFeature, getNavigationData} from '../../../../utils/api'; + +export const meta = { + title: 'Chart Provider', + package: '@twilio-paste/chart-provider', + description: packageJson.description, + slug: '/components/data-viz/chart-provider/', +}; + +export default ComponentPageLayout; + +export const getStaticProps = async () => { + const navigationData = await getNavigationData(); + const feature = await getFeature('Chart Provider'); + return { + props: { + data: { + ...packageJson, + ...feature, + }, + navigationData, + mdxHeadings, + pageHeaderData: { + categoryRoute: SidebarCategoryRoutes.COMPONENTS, + githubUrl: 'https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/chart-provider', + storybookUrl: '/?path=/story/components-chartprovider', //TODO: Update this to the correct storybook URL + }, + }, + }; +}; + + + {``} + + +## Guidelines + +## About Chart Provider + +## Examples + + + {``} + + +## Composition Notes + diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx new file mode 100644 index 0000000000..cfc6ff4a95 --- /dev/null +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx @@ -0,0 +1,57 @@ +export const meta = { + title: "Data Visualization", + description: "Display the supported chart types for the Paste Data Visualization library with coded examples.", + slug: "/foundations/data-visualization/engineering/chart-types", +}; + +import Image from "next/image"; +import Highcharts from "highcharts"; +import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; +import HighchartsReact from "highcharts-react-official"; +import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library"; + +import { Box } from "@twilio-paste/box"; +import { Heading } from "@twilio-paste/heading"; +import { Text } from "@twilio-paste/text"; +import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; +import { PageHeaderSeparator } from "@twilio-paste/page-header"; +import { Separator } from "@twilio-paste/separator"; +import { InlineCode } from "@twilio-paste/inline-code"; + +import { SidebarCategoryRoutes } from "../../../../constants"; +import DefaultLayout from "../../../../layouts/DefaultLayout"; +import { getNavigationData } from "../../../../utils/api"; + +export default DefaultLayout; + +export const getStaticProps = async () => { + const navigationData = await getNavigationData(); + return { + props: { + navigationData, + }, + }; +}; + + + + + + + + + + + + + + + + In progress + As our current data visualization offerings are in progress these documents are subject to change. We will revise and expand these pages when new chart types are supported. + + + + + + diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index 4a498c1f99..c240567351 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -1,6 +1,6 @@ export const meta = { title: "Data Visualization", - description: "An introduciton to building charts for engineers.", + description: "An overview of integrating Highcharts with Paste's data visualization components, including setup, licensing, and chart context.", slug: "/foundations/data-visualization/engineering/", }; @@ -56,21 +56,26 @@ export const getStaticProps = async () => { Our charting components are designed to work seamlessly with Highcharts. However, due to licensing restrictions, we cannot include Highcharts directly in our library. This limitation creates challenges when developing components for a library we cannot directly integrate with. -To address this, we have created components and wrappers that simplify the Highcharts API. These tools expose various props, allowing you to configure charts through a streamlined and user-friendly interface. The props are transformed into objects that Highcharts can interpret, and our components automatically apply styles to the charts for a consistent appearance. +To address this, we have created components and wrappers that simplify the Highcharts API. These tools expose various props, allowing you to configure charts through a streamlined and user-friendly interface. The props are transformed into objects that Highcharts can interpret, and our components automatically apply styles to the charts for a consistent appearance on a chart type bases. Global styles will be set in the `BaseChart` using our existing hook. + +## Licensing + +Paste does not provide a license for Twilio usage. Licenses are acquired on an applicaiton level. ODds are, if you are developing in one of our existing products you already have one. If you are creating a new application you may need to acquire a new license. ## Setup To ensure our components function correctly, some initial configuration is required in your project. This seciton will cover: - Storing and retrieving rendered chart objects. -- Setting up the chart context. - Adding any additional modules required for additional functionality such as gauges, exporting etc. -### Base chart - You will need to include a component that retrieves the chart configuration from our components' context and passes it to Highcharts. This component must also capture the rendered chart and store it in our `ChartContext`. Storing the rendered chart is essential for several reasons. It allows us to determine the positioning of elements relative to the screen, enabling the placement of components like tooltips. Additionally, it facilitates triggering update functions on the chart for interactions such as zooming or toggling the visibility of series through a legend component. +### BaseChart + +We recommend copying the below code and creating an instance of it in your application to use with our components. This component is designed to be reused across all charts. You do not need a new instance of this component for each chart. + Modules subject to change @@ -128,6 +133,13 @@ const Chart: React.FC = () => { export const BaseChart = React.memo(Chart); ``` +## Chart context + +We use React Context to store the rendered chart object to use in our components. When talking about the chart context we do not only mean the rendered object but also the initial configuration. You will need to pass data to the context for the BaseChart to read and use. + +Each individual chart instance will be wrapped in a [ChartProvider](/components/data-visualization/chart-provider) which sets the initial configuration and apply chart specific styles. + +An individual chart instance does not mean a chart only. It may also mean chart titles, legends, tooltips and any other component that does not sit in or on the chart canvas. In simpler terms, it is a container that wraps not only the Highcharts elements but any of our Paste components that interact with that chart instance. From 1f696ac54568863a369b5fd72638fad30dcb5f0a Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Mon, 14 Apr 2025 09:02:03 -0500 Subject: [PATCH 05/54] feat(data-viz): wip --- .../components/site-wrapper/sidebar/SidebarNavigation.tsx | 5 +++-- .../{data-visualization => }/chart-provider/api.mdx | 6 +++--- .../{data-visualization => }/chart-provider/changelog.mdx | 6 +++--- .../{data-visualization => }/chart-provider/index.mdx | 6 +++--- .../foundations/data-visualization/engineering/index.mdx | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) rename packages/paste-website/src/pages/components/{data-visualization => }/chart-provider/api.mdx (91%) rename packages/paste-website/src/pages/components/{data-visualization => }/chart-provider/changelog.mdx (82%) rename packages/paste-website/src/pages/components/{data-visualization => }/chart-provider/index.mdx (85%) diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index 84d6d8e2c7..bc132c004d 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -372,6 +372,7 @@ const SiteSidebarNavigation = (): JSX.Element => { if (name === "Sidebar Navigation") { return null; } + if(['Chart Provider'].includes(name)) {return null} if (name === "Data Visualization") { return ( { } > Chart Provider diff --git a/packages/paste-website/src/pages/components/data-visualization/chart-provider/api.mdx b/packages/paste-website/src/pages/components/chart-provider/api.mdx similarity index 91% rename from packages/paste-website/src/pages/components/data-visualization/chart-provider/api.mdx rename to packages/paste-website/src/pages/components/chart-provider/api.mdx index 87f5279e8f..bbbc7324e9 100644 --- a/packages/paste-website/src/pages/components/data-visualization/chart-provider/api.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/api.mdx @@ -1,9 +1,9 @@ import Changelog from '@twilio-paste/chart-provider/CHANGELOG.md'; // I don't know why this is needed but if you remove it the page fails to render import packageJson from '@twilio-paste/chart-provider/package.json'; -import {SidebarCategoryRoutes} from '../../../../constants'; -import ComponentPageLayout from '../../../../layouts/ComponentPageLayout'; -import {getFeature, getNavigationData, getComponentApi} from '../../../../utils/api'; +import {SidebarCategoryRoutes} from '../../../constants'; +import ComponentPageLayout from '../../../layouts/ComponentPageLayout'; +import {getFeature, getNavigationData, getComponentApi} from '../../../utils/api'; export const meta = { title: 'ChartProvider', diff --git a/packages/paste-website/src/pages/components/data-visualization/chart-provider/changelog.mdx b/packages/paste-website/src/pages/components/chart-provider/changelog.mdx similarity index 82% rename from packages/paste-website/src/pages/components/data-visualization/chart-provider/changelog.mdx rename to packages/paste-website/src/pages/components/chart-provider/changelog.mdx index 829b22e20c..db2af07583 100644 --- a/packages/paste-website/src/pages/components/data-visualization/chart-provider/changelog.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/changelog.mdx @@ -1,8 +1,8 @@ -import {SidebarCategoryRoutes} from '../../../../constants'; +import {SidebarCategoryRoutes} from '../../../constants'; import Changelog from '@twilio-paste/chart-provider/CHANGELOG.md'; import packageJson from '@twilio-paste/chart-provider/package.json'; -import ComponentPageLayout from '../../../../layouts/ComponentPageLayout'; -import {getFeature, getNavigationData} from '../../../../utils/api'; +import ComponentPageLayout from '../../../layouts/ComponentPageLayout'; +import {getFeature, getNavigationData} from '../../../utils/api'; export const meta = { title: 'Chart Provider', diff --git a/packages/paste-website/src/pages/components/data-visualization/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx similarity index 85% rename from packages/paste-website/src/pages/components/data-visualization/chart-provider/index.mdx rename to packages/paste-website/src/pages/components/chart-provider/index.mdx index 2d2741f82b..452abe8a97 100644 --- a/packages/paste-website/src/pages/components/data-visualization/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -1,9 +1,9 @@ import { ChartProvider } from '@twilio-paste/chart-provider'; import packageJson from '@twilio-paste/chart-provider/package.json'; -import {SidebarCategoryRoutes} from '../../../../constants'; -import ComponentPageLayout from '../../../../layouts/ComponentPageLayout'; -import {getFeature, getNavigationData} from '../../../../utils/api'; +import {SidebarCategoryRoutes} from '../../../constants'; +import ComponentPageLayout from '../../../layouts/ComponentPageLayout'; +import {getFeature, getNavigationData} from '../../../utils/api'; export const meta = { title: 'Chart Provider', diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index c240567351..df46982e07 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -137,7 +137,7 @@ export const BaseChart = React.memo(Chart); We use React Context to store the rendered chart object to use in our components. When talking about the chart context we do not only mean the rendered object but also the initial configuration. You will need to pass data to the context for the BaseChart to read and use. -Each individual chart instance will be wrapped in a [ChartProvider](/components/data-visualization/chart-provider) which sets the initial configuration and apply chart specific styles. +Each individual chart instance will be wrapped in a [ChartProvider](/components/chart-provider) which sets the initial configuration and apply chart specific styles. An individual chart instance does not mean a chart only. It may also mean chart titles, legends, tooltips and any other component that does not sit in or on the chart canvas. In simpler terms, it is a container that wraps not only the Highcharts elements but any of our Paste components that interact with that chart instance. From 427a1bde9d278fe837a742b058cf8e6060ee9b1b Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Mon, 14 Apr 2025 10:53:26 -0500 Subject: [PATCH 06/54] feat(data-viz): wip --- .../data-visualization/BaseChart.tsx | 47 +++++++++++++++ .../ChartProviderExamples.ts | 57 +++++++++++++++++++ .../pages/components/chart-provider/index.mdx | 16 ++++-- 3 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx create mode 100644 packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts diff --git a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx new file mode 100644 index 0000000000..e47c171be0 --- /dev/null +++ b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx @@ -0,0 +1,47 @@ +import { Box } from "@twilio-paste/box"; +import { ChartContext } from "@twilio-paste/chart-provider"; +import * as Highcharts from "highcharts"; +import HighchartsReact from "highcharts-react-official"; +import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; +import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library"; +import * as React from "react"; + + +const Chart: React.FC = () => { + applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); + const chartRef = React.useRef(null); + const { options, setChart, setChartRef } = React.useContext(ChartContext); + const [chartOptions, setChartOptions] = React.useState( + usePasteHighchartsTheme(options), + ); + + React.useLayoutEffect(() => { + setChartOptions(Highcharts.merge(chartOptions, options)); + }, [options]); + + React.useEffect(() => { + if (chartRef.current) { + setChartRef(chartRef.current); + } + }, [chartRef.current]); + + const callback = (chart: Highcharts.Chart) => { + if (chart?.series?.length > 0) { + setChart(chart); + } + }; + + return ( + + + + ); +}; + +export const ExamplesDataVizBaseChart = React.memo(Chart); \ No newline at end of file diff --git a/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts b/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts new file mode 100644 index 0000000000..189b053a16 --- /dev/null +++ b/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts @@ -0,0 +1,57 @@ +export const SimpleChartProviderExample = ` +const ChartProviderExample = () => { + const lineSeriesData = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + +export const CustomChartProviderExample = ` +const ChartProviderExample = () => { + const lineSeriesData = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + type: "line", + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + type: "line", + }, + { + name: "Sales & Distribution", + data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387], + type: "column", + }, + { + name: "Project Development", + data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227], + type: "column", + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 452abe8a97..7c7af0a51f 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -4,6 +4,8 @@ import packageJson from '@twilio-paste/chart-provider/package.json'; import {SidebarCategoryRoutes} from '../../../constants'; import ComponentPageLayout from '../../../layouts/ComponentPageLayout'; import {getFeature, getNavigationData} from '../../../utils/api'; +import {ExamplesDataVizBaseChart as BaseChart} from '../../../component-examples/data-visualization/BaseChart'; +import {CustomChartProviderExample, SimpleChartProviderExample} from '../../../component-examples/data-visualization/ChartProviderExamples'; export const meta = { title: 'Chart Provider', @@ -35,10 +37,11 @@ export const getStaticProps = async () => { }; - {``} +{SimpleChartProviderExample} ## Guidelines @@ -47,11 +50,16 @@ export const getStaticProps = async () => { ## Examples +### Custom Chart + + + - {``} +{CustomChartProviderExample} ## Composition Notes From 3ba67893328db16f95a0f3e4774375df94a8f747 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Mon, 14 Apr 2025 11:09:52 -0500 Subject: [PATCH 07/54] feat(data-viz): sitemap --- cypress/integration/sitemap-vrt/constants.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cypress/integration/sitemap-vrt/constants.ts b/cypress/integration/sitemap-vrt/constants.ts index fcf0b3ee93..ec3c4ca723 100644 --- a/cypress/integration/sitemap-vrt/constants.ts +++ b/cypress/integration/sitemap-vrt/constants.ts @@ -61,6 +61,7 @@ export const SITEMAP = [ "/components/card/", "/components/card/api", "/components/card/changelog", + "/components/chart-provider/", "/components/chat-composer/", "/components/chat-composer/api", "/components/chat-composer/changelog", @@ -284,6 +285,8 @@ export const SITEMAP = [ "/foundations/content/word-list/", "/foundations/illustrations/", "/foundations/data-visualization/", + "/foundations/data-visualization/engineering/", + "/foundations/data-visualization/engineering/chart-types/", "/foundations/spacing-and-layout/", "/foundations/typography/", "/inclusive-design/", From db4051033f8200b4f036a6aca38bd4baa29426dc Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Mon, 14 Apr 2025 11:14:56 -0500 Subject: [PATCH 08/54] feat(data-viz): docs exmapleds --- .../data-visualization/ChartProviderExamples.ts | 2 +- .../pages/components/chart-provider/index.mdx | 17 ++++++++++++++--- .../engineering/chart-types.mdx | 13 +++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts b/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts index 189b053a16..461f90b637 100644 --- a/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts +++ b/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts @@ -47,7 +47,7 @@ const ChartProviderExample = () => { ] return ( - + ); diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 7c7af0a51f..9b43d86651 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -1,4 +1,6 @@ import { ChartProvider } from '@twilio-paste/chart-provider'; +import { Box } from '@twilio-paste/box'; +import { Callout, CalloutHeading, CalloutText } from '@twilio-paste/callout'; import packageJson from '@twilio-paste/chart-provider/package.json'; import {SidebarCategoryRoutes} from '../../../constants'; @@ -48,11 +50,22 @@ export const getStaticProps = async () => { ## About Chart Provider +ChartProvider is a wrapper around Highcharts that provides a consistent API for configuring an individual chart instance. This component has no visible elements and is an engineering asset only. It acts as a store for chart options and provides a context for managing chart state. The ChartProvider component is responsible for rendering the chart and managing its lifecycle. + +We highly recommend using our [BaseChart](/foundations/data-visualization/engineering#basechart) code inside the ChartProvider to ensure that the chart is rendered correctly and state is correctly stored. + ## Examples -### Custom Chart +### Custom charts +You can use the `highchartsOptions` to create unsupported charts by passing options directly to the base chart without modification, but we recommend using our wrappers for easier migration, access to the rendered chart object, and enhanced custom interactions. + + + Compatibility + If you build charts using the Highcharts API it will be unlikely that our Paste components will function as they depend on helper funcitons and event tracking that we enrich the default options with. + + { {CustomChartProviderExample} -## Composition Notes - diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx index cfc6ff4a95..36ee511c35 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx @@ -14,6 +14,7 @@ import { Box } from "@twilio-paste/box"; import { Heading } from "@twilio-paste/heading"; import { Text } from "@twilio-paste/text"; import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; +import { ChartProvider } from "@twilio-paste/chart-provider"; import { PageHeaderSeparator } from "@twilio-paste/page-header"; import { Separator } from "@twilio-paste/separator"; import { InlineCode } from "@twilio-paste/inline-code"; @@ -21,6 +22,8 @@ import { InlineCode } from "@twilio-paste/inline-code"; import { SidebarCategoryRoutes } from "../../../../constants"; import DefaultLayout from "../../../../layouts/DefaultLayout"; import { getNavigationData } from "../../../../utils/api"; +import { CustomChartProviderExample } from "../../../../component-examples/data-visualization/ChartProviderExamples"; +import { ExamplesDataVizBaseChart as BaseChart } from "../../../../component-examples/data-visualization/BaseChart"; export default DefaultLayout; @@ -52,6 +55,16 @@ export const getStaticProps = async () => { +### Custom + + +{CustomChartProviderExample} + + From 1b602022813fa70e6dc5a0527e927e7ae1188618 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Mon, 14 Apr 2025 12:14:04 -0500 Subject: [PATCH 09/54] feat(data-viz): ci checks --- .../data-visualization/stories/base-chart.stories.tsx | 3 +-- .../data-visualization/stories/components/BaseChart.tsx | 2 +- .../component-examples/data-visualization/BaseChart.tsx | 7 ++----- .../components/site-wrapper/sidebar/SidebarNavigation.tsx | 4 +++- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/paste-libraries/data-visualization/stories/base-chart.stories.tsx b/packages/paste-libraries/data-visualization/stories/base-chart.stories.tsx index a1ddbdda1f..da83445912 100644 --- a/packages/paste-libraries/data-visualization/stories/base-chart.stories.tsx +++ b/packages/paste-libraries/data-visualization/stories/base-chart.stories.tsx @@ -1,9 +1,8 @@ import type { Meta, StoryFn } from "@storybook/react"; +import { ChartProvider } from "@twilio-paste/chart-provider"; import { Stack } from "@twilio-paste/stack"; import * as React from "react"; -/* eslint-enable */ -import { ChartProvider } from "@twilio-paste/chart-provider"; import { BaseChart } from "./components/BaseChart"; import { lineChartOptions } from "./options/lineChartOptions"; diff --git a/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx b/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx index c0e533d9c3..137003f155 100644 --- a/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx +++ b/packages/paste-libraries/data-visualization/stories/components/BaseChart.tsx @@ -26,7 +26,7 @@ const Chart: React.FC = () => { } }, [chartRef.current]); - const callback = (chart: Highcharts.Chart) => { + const callback = (chart: Highcharts.Chart): void => { if (chart?.series?.length > 0) { setChart(chart); } diff --git a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx index e47c171be0..92da437fda 100644 --- a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx +++ b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx @@ -6,14 +6,11 @@ import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library"; import * as React from "react"; - const Chart: React.FC = () => { applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); const chartRef = React.useRef(null); const { options, setChart, setChartRef } = React.useContext(ChartContext); - const [chartOptions, setChartOptions] = React.useState( - usePasteHighchartsTheme(options), - ); + const [chartOptions, setChartOptions] = React.useState(usePasteHighchartsTheme(options)); React.useLayoutEffect(() => { setChartOptions(Highcharts.merge(chartOptions, options)); @@ -44,4 +41,4 @@ const Chart: React.FC = () => { ); }; -export const ExamplesDataVizBaseChart = React.memo(Chart); \ No newline at end of file +export const ExamplesDataVizBaseChart = React.memo(Chart); diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index bc132c004d..e7f0782452 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -372,7 +372,9 @@ const SiteSidebarNavigation = (): JSX.Element => { if (name === "Sidebar Navigation") { return null; } - if(['Chart Provider'].includes(name)) {return null} + if (["Chart Provider"].includes(name)) { + return null; + } if (name === "Data Visualization") { return ( Date: Wed, 16 Apr 2025 10:19:24 -0500 Subject: [PATCH 10/54] feat(data-viz): docs refinement --- .../src/pages/components/chart-provider/index.mdx | 6 +++--- .../data-visualization/engineering/index.mdx | 10 +++++----- .../src/pages/foundations/data-visualization/index.mdx | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 9b43d86651..c84b1a24d2 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -50,7 +50,7 @@ export const getStaticProps = async () => { ## About Chart Provider -ChartProvider is a wrapper around Highcharts that provides a consistent API for configuring an individual chart instance. This component has no visible elements and is an engineering asset only. It acts as a store for chart options and provides a context for managing chart state. The ChartProvider component is responsible for rendering the chart and managing its lifecycle. +Chart Provider is a wrapper around Highcharts that provides a consistent API for configuring an individual chart instance. This component has no visible elements and is an engineering asset only. It acts as a store for chart options and provides a context for managing chart state. We highly recommend using our [BaseChart](/foundations/data-visualization/engineering#basechart) code inside the ChartProvider to ensure that the chart is rendered correctly and state is correctly stored. @@ -58,12 +58,12 @@ We highly recommend using our [BaseChart](/foundations/data-visualization/engine ### Custom charts -You can use the `highchartsOptions` to create unsupported charts by passing options directly to the base chart without modification, but we recommend using our wrappers for easier migration, access to the rendered chart object, and enhanced custom interactions. +You can use the `highchartsOptions` to create unsupported charts by passing the Higcharts config directly to the base chart without modification. We recommend using our wrappers for easier migration and a simpler way of accessing the rendered chart object for building custom interactions. Compatibility - If you build charts using the Highcharts API it will be unlikely that our Paste components will function as they depend on helper funcitons and event tracking that we enrich the default options with. + If you build charts using the Highcharts API it will be unlikely that our Paste data visualization components will function correctly as they depend on helper funcitons and event tracking that we enrich the default options with. diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index df46982e07..525ee8f2ec 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -54,13 +54,13 @@ export const getStaticProps = async () => { -Our charting components are designed to work seamlessly with Highcharts. However, due to licensing restrictions, we cannot include Highcharts directly in our library. This limitation creates challenges when developing components for a library we cannot directly integrate with. +Our charting components are designed to work seamlessly with Highcharts. However, due to licensing restrictions, we cannot include Highcharts directly in our library. This limitation creates challenges when developing components for a library we cannot directly interact with. To address this, we have created components and wrappers that simplify the Highcharts API. These tools expose various props, allowing you to configure charts through a streamlined and user-friendly interface. The props are transformed into objects that Highcharts can interpret, and our components automatically apply styles to the charts for a consistent appearance on a chart type bases. Global styles will be set in the `BaseChart` using our existing hook. ## Licensing -Paste does not provide a license for Twilio usage. Licenses are acquired on an applicaiton level. ODds are, if you are developing in one of our existing products you already have one. If you are creating a new application you may need to acquire a new license. +Paste does not provide a license for Twilio usage. Licenses are acquired on an applicaiton level. If you are developing in one of our existing products it is highly likely licenses are already purchased. If you are creating a new application you may need to acquire a new license. If you need further information you can reach out to us via [GitHub discussions](https://github.com/twilio-labs/paste/discussions/new?category=q-a) or the Procurement team. ## Setup @@ -68,7 +68,7 @@ To ensure our components function correctly, some initial configuration is requi - Storing and retrieving rendered chart objects. - Adding any additional modules required for additional functionality such as gauges, exporting etc. -You will need to include a component that retrieves the chart configuration from our components' context and passes it to Highcharts. This component must also capture the rendered chart and store it in our `ChartContext`. +You will need to include a component that retrieves the chart configuration from our [ChartProvider](/components/chart-provider)'s context and passes it to Highcharts. This component must also capture the rendered chart and store it in the Chart Provider context. Storing the rendered chart is essential for several reasons. It allows us to determine the positioning of elements relative to the screen, enabling the placement of components like tooltips. Additionally, it facilitates triggering update functions on the chart for interactions such as zooming or toggling the visibility of series through a legend component. @@ -135,11 +135,11 @@ export const BaseChart = React.memo(Chart); ``` ## Chart context -We use React Context to store the rendered chart object to use in our components. When talking about the chart context we do not only mean the rendered object but also the initial configuration. You will need to pass data to the context for the BaseChart to read and use. +We use React Context to store the rendered chart object to use in our components. When talking about the chart context we do not only mean the rendered object but also the initial configuration. You will need to pass data to the context for the `BaseChart` to read and use. Each individual chart instance will be wrapped in a [ChartProvider](/components/chart-provider) which sets the initial configuration and apply chart specific styles. -An individual chart instance does not mean a chart only. It may also mean chart titles, legends, tooltips and any other component that does not sit in or on the chart canvas. In simpler terms, it is a container that wraps not only the Highcharts elements but any of our Paste components that interact with that chart instance. +An individual chart instance does not mean a chart only. It may also mean chart titles, legends, tooltips and any other component that does not sit in or on the chart canvas. In simpler terms, it is a container that wraps not only the Highcharts elements but any of our Paste components that interact with that chart and canvas. diff --git a/packages/paste-website/src/pages/foundations/data-visualization/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/index.mdx index 1cfa7b47ca..c9443ee2ee 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/index.mdx @@ -67,7 +67,7 @@ This foundation page was created to help establish a familiar and accessible use Paste Chart support - We're actively working on full charting support through a suite of Paste components designed to make it easy to build pre-styled, interactive charts. As we expand these capabilities, we’ll continue adding more examples and documentation in the Engineering section. We plan to roll out support for additional chart types over time and recommend using our components if they fit your current needs. + We're actively working on full charting support through a suite of Paste components designed to make it easy to build pre-styled, interactive charts. As we expand these capabilities, we will continue adding more examples and documentation in the Engineering section. We plan to roll out support for additional chart types over time and recommend using our components if they fit your current needs. From 1b5bc22b3de1f63c507e30d9a5b95f17ac6ac312 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 10:24:55 -0500 Subject: [PATCH 11/54] chore(cleanup): remove redundant story --- .../components/list/stories/index.stories.tsx | 42 +------------------ 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/packages/paste-core/components/list/stories/index.stories.tsx b/packages/paste-core/components/list/stories/index.stories.tsx index 225674ba0a..d48d50dc83 100644 --- a/packages/paste-core/components/list/stories/index.stories.tsx +++ b/packages/paste-core/components/list/stories/index.stories.tsx @@ -5,7 +5,7 @@ import { Stack } from "@twilio-paste/stack"; import { useTheme } from "@twilio-paste/theme"; import * as React from "react"; -import { List, ListItem, OrderedList, UnorderedList } from "../src"; +import { ListItem, OrderedList, UnorderedList } from "../src"; // eslint-disable-next-line import/no-default-export export default { @@ -110,46 +110,6 @@ export const NestedUnorderedList = (): React.ReactNode => { ); }; -export const DefaultList = (): React.ReactNode => { - return ( - <> - - - Deliver critical time-sensitive messages to employees and customers at scale with the Programmable Messaging - API. - - - - Deliver critical time-sensitive messages to employees and customers at scale with the Programmable Messaging - API. - - - - Deliver critical time-sensitive messages to employees and customers at scale with the Programmable - Messaging API. - - - Proactively inform customers about account activity, purchase confirmations, and shipping notifications - with the - Programmable Messaging API. - - - - Proactively inform customers about account activity, purchase confirmations, and shipping notifications with - the - Programmable Messaging API. - - - - Proactively inform customers about account activity, purchase confirmations, and shipping notifications with - the - Programmable Messaging API. - - - - ); -}; - export const CustomOrderedList: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( From bb8c48be31b2d09759fcdd0ac314af6f2f1d2c8a Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 10:29:45 -0500 Subject: [PATCH 12/54] chore(cleanup): changeset --- .changeset/cuddly-berries-explain.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/cuddly-berries-explain.md diff --git a/.changeset/cuddly-berries-explain.md b/.changeset/cuddly-berries-explain.md new file mode 100644 index 0000000000..ecfe88f3d1 --- /dev/null +++ b/.changeset/cuddly-berries-explain.md @@ -0,0 +1,6 @@ +--- +"@twilio-paste/core": minor +"@twilio-paste/data-visualization-library": minor +--- + +[Data Visualization Library] update Highcharts native tooltip styles to align more closely with Paste styles including correctly setting the font family From 7d0d76bfa7e48663d0811d7bb703d04aff0c1aa1 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 10:33:52 -0500 Subject: [PATCH 13/54] fix(data-viz): fix urls --- .../components/site-wrapper/sidebar/SidebarNavigation.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index e7f0782452..5a2b416715 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -372,20 +372,20 @@ const SiteSidebarNavigation = (): JSX.Element => { if (name === "Sidebar Navigation") { return null; } - if (["Chart Provider"].includes(name)) { + if (["Data Visualization"].includes(name)) { return null; } - if (name === "Data Visualization") { + if (name === "Chart Provider") { return ( event({ category: "Left Navigation", action: `click-${name}`, - label: name, + label: "Data Visualization", }) } > From d828fb3e6acffcea74742e40478c535e7e547142 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 10:35:46 -0500 Subject: [PATCH 14/54] fix(data-viz): fix slugs --- .../paste-website/src/pages/components/chart-provider/api.mdx | 2 +- .../src/pages/components/chart-provider/changelog.mdx | 2 +- .../paste-website/src/pages/components/chart-provider/index.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/paste-website/src/pages/components/chart-provider/api.mdx b/packages/paste-website/src/pages/components/chart-provider/api.mdx index bbbc7324e9..68a507997a 100644 --- a/packages/paste-website/src/pages/components/chart-provider/api.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/api.mdx @@ -9,7 +9,7 @@ export const meta = { title: 'ChartProvider', package: '@twilio-paste/chart-provider', description: packageJson.description, - slug: '/components/chart-provider/api', + slug: '/components/chart-provider/api/', }; export default ComponentPageLayout; diff --git a/packages/paste-website/src/pages/components/chart-provider/changelog.mdx b/packages/paste-website/src/pages/components/chart-provider/changelog.mdx index db2af07583..019de7af08 100644 --- a/packages/paste-website/src/pages/components/chart-provider/changelog.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/changelog.mdx @@ -8,7 +8,7 @@ export const meta = { title: 'Chart Provider', package: '@twilio-paste/chart-provider', description: packageJson.description, - slug: '/components/chart-provider/changelog', + slug: '/components/chart-provider/changelog/', }; export default ComponentPageLayout; diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index c84b1a24d2..7ff1a313cc 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -13,7 +13,7 @@ export const meta = { title: 'Chart Provider', package: '@twilio-paste/chart-provider', description: packageJson.description, - slug: '/components/data-viz/chart-provider/', + slug: '/components/chart-provider/', }; export default ComponentPageLayout; From 8b7fcf498cb7bd19474a54a93611d0af3a642e9e Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 10:48:02 -0500 Subject: [PATCH 15/54] feat(data-vix): chart-provider in project.json --- packages/paste-website/package.json | 1 + .../src/component-examples/data-visualization/BaseChart.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/paste-website/package.json b/packages/paste-website/package.json index 122ebf5c10..4dbe7a8ae6 100644 --- a/packages/paste-website/package.json +++ b/packages/paste-website/package.json @@ -52,6 +52,7 @@ "@twilio-paste/card": "^10.1.0", "@twilio-paste/chat-composer": "^6.0.1", "@twilio-paste/chat-log": "^6.0.1", + "@twilio-paste/chart-provider": "^2.0.1", "@twilio-paste/checkbox": "^14.0.1", "@twilio-paste/clipboard-copy-library": "^4.0.1", "@twilio-paste/code-block": "^6.0.1", diff --git a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx index 92da437fda..b9ad272c36 100644 --- a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx +++ b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx @@ -1,9 +1,9 @@ import { Box } from "@twilio-paste/box"; import { ChartContext } from "@twilio-paste/chart-provider"; +import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library"; import * as Highcharts from "highcharts"; import HighchartsReact from "highcharts-react-official"; import HighchartsAccessibilityModule from "highcharts/modules/accessibility"; -import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library"; import * as React from "react"; const Chart: React.FC = () => { @@ -22,7 +22,7 @@ const Chart: React.FC = () => { } }, [chartRef.current]); - const callback = (chart: Highcharts.Chart) => { + const callback = (chart: Highcharts.Chart): void => { if (chart?.series?.length > 0) { setChart(chart); } From 2297ca32ef69ba3dadff1644fb0fc35a78e4ff13 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 10:51:37 -0500 Subject: [PATCH 16/54] chore(data-vix): test chanpshots --- .../__test__/__snapshots__/index.spec.tsx.snap | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/paste-libraries/data-visualization/__test__/__snapshots__/index.spec.tsx.snap b/packages/paste-libraries/data-visualization/__test__/__snapshots__/index.spec.tsx.snap index 1e7b20ed73..f8bb776329 100644 --- a/packages/paste-libraries/data-visualization/__test__/__snapshots__/index.spec.tsx.snap +++ b/packages/paste-libraries/data-visualization/__test__/__snapshots__/index.spec.tsx.snap @@ -131,9 +131,15 @@ Object { "text": "Solar Employment Growth by Sector, 2010-2016", }, "tooltip": Object { - "backgroundColor": "rgb(244, 244, 246)", + "backgroundColor": "rgb(18, 28, 45)", + "borderColor": "rgb(136, 145, 170)", + "borderRadius": "8", + "borderWidth": "1px", + "padding": 12, "style": Object { "color": "rgb(18, 28, 45)", + "fontFamily": "'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif", + "fontSize": "0.875rem", }, }, "xAxis": Object { @@ -228,9 +234,15 @@ Object { }, }, "tooltip": Object { - "backgroundColor": "rgb(244, 244, 246)", + "backgroundColor": "rgb(18, 28, 45)", + "borderColor": "rgb(136, 145, 170)", + "borderRadius": "8", + "borderWidth": "1px", + "padding": 12, "style": Object { "color": "rgb(18, 28, 45)", + "fontFamily": "'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif", + "fontSize": "0.875rem", }, }, "xAxis": Object { From 882cefca4d6f45e4df86b127e4f010773f130e81 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 10:57:49 -0500 Subject: [PATCH 17/54] chore(ci): fix supabase --- apps/backend/package.json | 2 +- apps/backend/supabase/schema.gen.ts | 273 ++++++++++------------------ packages/paste-website/package.json | 2 +- yarn.lock | 11 +- 4 files changed, 108 insertions(+), 180 deletions(-) diff --git a/apps/backend/package.json b/apps/backend/package.json index ef7b193cbc..b6d95281e9 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -9,6 +9,6 @@ "db:reset": "yarn supabase db reset" }, "devDependencies": { - "supabase": "^2.6.8" + "supabase": "^2.8.1" } } diff --git a/apps/backend/supabase/schema.gen.ts b/apps/backend/supabase/schema.gen.ts index d7c0e7c109..85cc661288 100644 --- a/apps/backend/supabase/schema.gen.ts +++ b/apps/backend/supabase/schema.gen.ts @@ -225,23 +225,12 @@ export type Database = { [_ in never]: never } Functions: { - binary_quantize: - | { - Args: { - "": string - } - Returns: unknown - } - | { - Args: { - "": unknown - } - Returns: unknown - } + binary_quantize: { + Args: { "": string } | { "": unknown } + Returns: unknown + } get_page_parents: { - Args: { - page_id: number - } + Args: { page_id: number } Returns: { id: number parent_page_id: number @@ -250,103 +239,57 @@ export type Database = { }[] } halfvec_avg: { - Args: { - "": number[] - } + Args: { "": number[] } Returns: unknown } halfvec_out: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: unknown } halfvec_send: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: string } halfvec_typmod_in: { - Args: { - "": unknown[] - } + Args: { "": unknown[] } Returns: number } hnsw_bit_support: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: unknown } hnsw_halfvec_support: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: unknown } hnsw_sparsevec_support: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: unknown } hnswhandler: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: unknown } ivfflat_bit_support: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: unknown } ivfflat_halfvec_support: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: unknown } ivfflathandler: { - Args: { - "": unknown - } + Args: { "": unknown } + Returns: unknown + } + l2_norm: { + Args: { "": unknown } | { "": unknown } + Returns: number + } + l2_normalize: { + Args: { "": string } | { "": unknown } | { "": unknown } Returns: unknown } - l2_norm: - | { - Args: { - "": unknown - } - Returns: number - } - | { - Args: { - "": unknown - } - Returns: number - } - l2_normalize: - | { - Args: { - "": string - } - Returns: string - } - | { - Args: { - "": unknown - } - Returns: unknown - } - | { - Args: { - "": unknown - } - Returns: unknown - } match_discussions: { Args: { embedding: string @@ -420,21 +363,15 @@ export type Database = { }[] } sparsevec_out: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: unknown } sparsevec_send: { - Args: { - "": unknown - } + Args: { "": unknown } Returns: string } sparsevec_typmod_in: { - Args: { - "": unknown[] - } + Args: { "": unknown[] } Returns: number } upsert_story_and_create_story_render: { @@ -450,46 +387,27 @@ export type Database = { Returns: undefined } vector_avg: { - Args: { - "": number[] - } + Args: { "": number[] } Returns: string } - vector_dims: - | { - Args: { - "": string - } - Returns: number - } - | { - Args: { - "": unknown - } - Returns: number - } + vector_dims: { + Args: { "": string } | { "": unknown } + Returns: number + } vector_norm: { - Args: { - "": string - } + Args: { "": string } Returns: number } vector_out: { - Args: { - "": string - } + Args: { "": string } Returns: unknown } vector_send: { - Args: { - "": string - } + Args: { "": string } Returns: string } vector_typmod_in: { - Args: { - "": unknown[] - } + Args: { "": unknown[] } Returns: number } } @@ -719,30 +637,19 @@ export type Database = { } Functions: { can_insert_object: { - Args: { - bucketid: string - name: string - owner: string - metadata: Json - } + Args: { bucketid: string; name: string; owner: string; metadata: Json } Returns: undefined } extension: { - Args: { - name: string - } + Args: { name: string } Returns: string } filename: { - Args: { - name: string - } + Args: { name: string } Returns: string } foldername: { - Args: { - name: string - } + Args: { name: string } Returns: string[] } get_size_by_bucket: { @@ -817,27 +724,29 @@ export type Database = { } } -type PublicSchema = Database[Extract] +type DefaultSchema = Database[Extract] export type Tables< - PublicTableNameOrOptions extends - | keyof (PublicSchema["Tables"] & PublicSchema["Views"]) + DefaultSchemaTableNameOrOptions extends + | keyof (DefaultSchema["Tables"] & DefaultSchema["Views"]) | { schema: keyof Database }, - TableName extends PublicTableNameOrOptions extends { schema: keyof Database } - ? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] & - Database[PublicTableNameOrOptions["schema"]]["Views"]) + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof Database + } + ? keyof (Database[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & + Database[DefaultSchemaTableNameOrOptions["schema"]]["Views"]) : never = never, -> = PublicTableNameOrOptions extends { schema: keyof Database } - ? (Database[PublicTableNameOrOptions["schema"]]["Tables"] & - Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends { +> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database } + ? (Database[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & + Database[DefaultSchemaTableNameOrOptions["schema"]]["Views"])[TableName] extends { Row: infer R } ? R : never - : PublicTableNameOrOptions extends keyof (PublicSchema["Tables"] & - PublicSchema["Views"]) - ? (PublicSchema["Tables"] & - PublicSchema["Views"])[PublicTableNameOrOptions] extends { + : DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema["Tables"] & + DefaultSchema["Views"]) + ? (DefaultSchema["Tables"] & + DefaultSchema["Views"])[DefaultSchemaTableNameOrOptions] extends { Row: infer R } ? R @@ -845,20 +754,22 @@ export type Tables< : never export type TablesInsert< - PublicTableNameOrOptions extends - | keyof PublicSchema["Tables"] + DefaultSchemaTableNameOrOptions extends + | keyof DefaultSchema["Tables"] | { schema: keyof Database }, - TableName extends PublicTableNameOrOptions extends { schema: keyof Database } - ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"] + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof Database + } + ? keyof Database[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] : never = never, -> = PublicTableNameOrOptions extends { schema: keyof Database } - ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends { +> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database } + ? Database[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { Insert: infer I } ? I : never - : PublicTableNameOrOptions extends keyof PublicSchema["Tables"] - ? PublicSchema["Tables"][PublicTableNameOrOptions] extends { + : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] + ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { Insert: infer I } ? I @@ -866,20 +777,22 @@ export type TablesInsert< : never export type TablesUpdate< - PublicTableNameOrOptions extends - | keyof PublicSchema["Tables"] + DefaultSchemaTableNameOrOptions extends + | keyof DefaultSchema["Tables"] | { schema: keyof Database }, - TableName extends PublicTableNameOrOptions extends { schema: keyof Database } - ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"] + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof Database + } + ? keyof Database[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] : never = never, -> = PublicTableNameOrOptions extends { schema: keyof Database } - ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends { +> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database } + ? Database[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { Update: infer U } ? U : never - : PublicTableNameOrOptions extends keyof PublicSchema["Tables"] - ? PublicSchema["Tables"][PublicTableNameOrOptions] extends { + : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] + ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { Update: infer U } ? U @@ -887,21 +800,23 @@ export type TablesUpdate< : never export type Enums< - PublicEnumNameOrOptions extends - | keyof PublicSchema["Enums"] + DefaultSchemaEnumNameOrOptions extends + | keyof DefaultSchema["Enums"] | { schema: keyof Database }, - EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database } - ? keyof Database[PublicEnumNameOrOptions["schema"]]["Enums"] + EnumName extends DefaultSchemaEnumNameOrOptions extends { + schema: keyof Database + } + ? keyof Database[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"] : never = never, -> = PublicEnumNameOrOptions extends { schema: keyof Database } - ? Database[PublicEnumNameOrOptions["schema"]]["Enums"][EnumName] - : PublicEnumNameOrOptions extends keyof PublicSchema["Enums"] - ? PublicSchema["Enums"][PublicEnumNameOrOptions] +> = DefaultSchemaEnumNameOrOptions extends { schema: keyof Database } + ? Database[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"][EnumName] + : DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema["Enums"] + ? DefaultSchema["Enums"][DefaultSchemaEnumNameOrOptions] : never export type CompositeTypes< PublicCompositeTypeNameOrOptions extends - | keyof PublicSchema["CompositeTypes"] + | keyof DefaultSchema["CompositeTypes"] | { schema: keyof Database }, CompositeTypeName extends PublicCompositeTypeNameOrOptions extends { schema: keyof Database @@ -910,7 +825,19 @@ export type CompositeTypes< : never = never, > = PublicCompositeTypeNameOrOptions extends { schema: keyof Database } ? Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName] - : PublicCompositeTypeNameOrOptions extends keyof PublicSchema["CompositeTypes"] - ? PublicSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] + : PublicCompositeTypeNameOrOptions extends keyof DefaultSchema["CompositeTypes"] + ? DefaultSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] : never +export const Constants = { + graphql_public: { + Enums: {}, + }, + public: { + Enums: {}, + }, + storage: { + Enums: {}, + }, +} as const + diff --git a/packages/paste-website/package.json b/packages/paste-website/package.json index 4dbe7a8ae6..9eefcbc269 100644 --- a/packages/paste-website/package.json +++ b/packages/paste-website/package.json @@ -50,9 +50,9 @@ "@twilio-paste/button-group": "^5.0.1", "@twilio-paste/callout": "^5.0.1", "@twilio-paste/card": "^10.1.0", + "@twilio-paste/chart-provider": "^2.0.1", "@twilio-paste/chat-composer": "^6.0.1", "@twilio-paste/chat-log": "^6.0.1", - "@twilio-paste/chart-provider": "^2.0.1", "@twilio-paste/checkbox": "^14.0.1", "@twilio-paste/clipboard-copy-library": "^4.0.1", "@twilio-paste/code-block": "^6.0.1", diff --git a/yarn.lock b/yarn.lock index c6b43a1128..62fc01cb97 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11099,7 +11099,7 @@ __metadata: version: 0.0.0-use.local resolution: "@twilio-paste/backend@workspace:apps/backend" dependencies: - supabase: ^2.6.8 + supabase: ^2.8.1 languageName: unknown linkType: soft @@ -15770,6 +15770,7 @@ __metadata: "@twilio-paste/button-group": ^5.0.1 "@twilio-paste/callout": ^5.0.1 "@twilio-paste/card": ^10.1.0 + "@twilio-paste/chart-provider": ^2.0.1 "@twilio-paste/chat-composer": ^6.0.1 "@twilio-paste/chat-log": ^6.0.1 "@twilio-paste/checkbox": ^14.0.1 @@ -43343,9 +43344,9 @@ resolve@^2.0.0-next.3: languageName: node linkType: hard -"supabase@npm:^2.6.8": - version: 2.8.1 - resolution: "supabase@npm:2.8.1" +"supabase@npm:^2.8.1": + version: 2.22.1 + resolution: "supabase@npm:2.22.1" dependencies: bin-links: ^5.0.0 https-proxy-agent: ^7.0.2 @@ -43353,7 +43354,7 @@ resolve@^2.0.0-next.3: tar: 7.4.3 bin: supabase: bin/supabase - checksum: 10b240963da4263ad8d03e84b97939504f5690eb894a9ee8ae225d69c0b8f31a890e9e24e9d4b2757c714eb38addb6878f6e531f9f7279c22de50a991b8e7cd4 + checksum: 2b12441bc6754b6b845e91765b2b7585aae7af944fb77d20f52e4894e70761650dfb148453c83a6eaee426bba5e2f28da2200e8f4f86a31fbc34dc70f35f4c84 languageName: node linkType: hard From 65f2844b212c4903283e87a1b32717746d556aa9 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 11:03:03 -0500 Subject: [PATCH 18/54] chore(ci): fix supabase --- apps/backend/supabase/schema.gen.ts | 112 ++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/apps/backend/supabase/schema.gen.ts b/apps/backend/supabase/schema.gen.ts index 85cc661288..b471f2dd96 100644 --- a/apps/backend/supabase/schema.gen.ts +++ b/apps/backend/supabase/schema.gen.ts @@ -486,6 +486,7 @@ export type Database = { created_at: string | null id: string last_accessed_at: string | null + level: number | null metadata: Json | null name: string | null owner: string | null @@ -500,6 +501,7 @@ export type Database = { created_at?: string | null id?: string last_accessed_at?: string | null + level?: number | null metadata?: Json | null name?: string | null owner?: string | null @@ -514,6 +516,7 @@ export type Database = { created_at?: string | null id?: string last_accessed_at?: string | null + level?: number | null metadata?: Json | null name?: string | null owner?: string | null @@ -533,6 +536,38 @@ export type Database = { }, ] } + prefixes: { + Row: { + bucket_id: string + created_at: string | null + level: number + name: string + updated_at: string | null + } + Insert: { + bucket_id: string + created_at?: string | null + level?: number + name: string + updated_at?: string | null + } + Update: { + bucket_id?: string + created_at?: string | null + level?: number + name?: string + updated_at?: string | null + } + Relationships: [ + { + foreignKeyName: "prefixes_bucketId_fkey" + columns: ["bucket_id"] + isOneToOne: false + referencedRelation: "buckets" + referencedColumns: ["id"] + }, + ] + } s3_multipart_uploads: { Row: { bucket_id: string @@ -636,10 +671,18 @@ export type Database = { [_ in never]: never } Functions: { + add_prefixes: { + Args: { _bucket_id: string; _name: string } + Returns: undefined + } can_insert_object: { Args: { bucketid: string; name: string; owner: string; metadata: Json } Returns: undefined } + delete_prefix: { + Args: { _bucket_id: string; _name: string } + Returns: boolean + } extension: { Args: { name: string } Returns: string @@ -652,6 +695,18 @@ export type Database = { Args: { name: string } Returns: string[] } + get_level: { + Args: { name: string } + Returns: number + } + get_prefix: { + Args: { name: string } + Returns: string + } + get_prefixes: { + Args: { name: string } + Returns: string[] + } get_size_by_bucket: { Args: Record Returns: { @@ -714,6 +769,63 @@ export type Database = { metadata: Json }[] } + search_legacy_v1: { + Args: { + prefix: string + bucketname: string + limits?: number + levels?: number + offsets?: number + search?: string + sortcolumn?: string + sortorder?: string + } + Returns: { + name: string + id: string + updated_at: string + created_at: string + last_accessed_at: string + metadata: Json + }[] + } + search_v1_optimised: { + Args: { + prefix: string + bucketname: string + limits?: number + levels?: number + offsets?: number + search?: string + sortcolumn?: string + sortorder?: string + } + Returns: { + name: string + id: string + updated_at: string + created_at: string + last_accessed_at: string + metadata: Json + }[] + } + search_v2: { + Args: { + prefix: string + bucket_name: string + limits?: number + levels?: number + start_after?: string + } + Returns: { + key: string + name: string + id: string + updated_at: string + created_at: string + metadata: Json + }[] + } } Enums: { [_ in never]: never From 3f21680540b24922200f4c6a087286f0f624e934 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 11:21:24 -0500 Subject: [PATCH 19/54] chore(ci): ignore generated files for linting --- .eslintignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.eslintignore b/.eslintignore index 009797d238..6aee0e1c31 100644 --- a/.eslintignore +++ b/.eslintignore @@ -19,3 +19,5 @@ packages/**/dist/* tsconfig.build.tsbuildinfo **/*.d.ts + +apps/backend/supabase/schema.gen.ts From e4b069af750e7ed17b72bbe431eff85c8aa2df3c Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 11:38:48 -0500 Subject: [PATCH 20/54] chore(data-vix): typos --- .../paste-website/src/pages/components/chart-provider/index.mdx | 2 +- .../pages/foundations/data-visualization/engineering/index.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 7ff1a313cc..54d1a57572 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -63,7 +63,7 @@ You can use the `highchartsOptions` to create unsupported charts by passing the Compatibility - If you build charts using the Highcharts API it will be unlikely that our Paste data visualization components will function correctly as they depend on helper funcitons and event tracking that we enrich the default options with. + If you build charts using the Highcharts API it will be unlikely that our Paste data visualization components will function correctly as they depend on helper functions and event tracking that we enrich the default options with. diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index 525ee8f2ec..d6be3e1c6d 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -60,7 +60,7 @@ To address this, we have created components and wrappers that simplify the Highc ## Licensing -Paste does not provide a license for Twilio usage. Licenses are acquired on an applicaiton level. If you are developing in one of our existing products it is highly likely licenses are already purchased. If you are creating a new application you may need to acquire a new license. If you need further information you can reach out to us via [GitHub discussions](https://github.com/twilio-labs/paste/discussions/new?category=q-a) or the Procurement team. +Paste does not provide a license for Twilio usage. Licenses are acquired on an application level. If you are developing in one of our existing products it is highly likely licenses are already purchased. If you are creating a new application you may need to acquire a new license. If you need further information you can reach out to us via [GitHub discussions](https://github.com/twilio-labs/paste/discussions/new?category=q-a) or the Procurement team. ## Setup From 856fa9623459937edb9d3c565be366b0028e5bea Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 12:11:52 -0500 Subject: [PATCH 21/54] chore(data-vix): trigger rebuild --- .../pages/foundations/data-visualization/engineering/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index d6be3e1c6d..e5e954c906 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -133,6 +133,7 @@ const Chart: React.FC = () => { export const BaseChart = React.memo(Chart); ``` + ## Chart context We use React Context to store the rendered chart object to use in our components. When talking about the chart context we do not only mean the rendered object but also the initial configuration. You will need to pass data to the context for the `BaseChart` to read and use. From fa6c7b48a45baaf99df93e3fad77429af731b152 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 14:58:50 -0500 Subject: [PATCH 22/54] chore(data-vix): trigger rebuild --- .../pages/foundations/data-visualization/engineering/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index e5e954c906..a23c1ff25d 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -144,4 +144,4 @@ An individual chart instance does not mean a chart only. It may also mean chart - + \ No newline at end of file From 34bcf1e3cb5d0dba3611cd546d3050abc487fd6d Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 16 Apr 2025 14:58:56 -0500 Subject: [PATCH 23/54] chore(data-vix): trigger rebuild --- .../pages/foundations/data-visualization/engineering/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx index a23c1ff25d..e5e954c906 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx @@ -144,4 +144,4 @@ An individual chart instance does not mean a chart only. It may also mean chart - \ No newline at end of file + From dfcc8fc1a15b3f6c18f299924c86e554198bd81c Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 22 Apr 2025 13:37:01 -0500 Subject: [PATCH 24/54] feat(data-visualization): add initial supported charts --- .../chart-provider/src/ChartProvider.tsx | 41 ++++- .../data-visualization/src/index.tsx | 2 + .../src/transformers/baseFormatter.ts | 78 +++++++++ .../src/transformers/columnChart.ts | 47 ++++++ .../src/transformers/index.ts | 26 +++ .../src/transformers/lineChart.ts | 28 ++++ .../data-visualization/src/types.ts | 67 ++++++++ .../stories/supported-charts.stories.tsx | 149 ++++++++++++++++++ .../stories/supported-data/column.ts | 16 ++ .../stories/supported-data/line.ts | 24 +++ 10 files changed, 474 insertions(+), 4 deletions(-) create mode 100644 packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts create mode 100644 packages/paste-libraries/data-visualization/src/transformers/columnChart.ts create mode 100644 packages/paste-libraries/data-visualization/src/transformers/index.ts create mode 100644 packages/paste-libraries/data-visualization/src/transformers/lineChart.ts create mode 100644 packages/paste-libraries/data-visualization/src/types.ts create mode 100644 packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx create mode 100644 packages/paste-libraries/data-visualization/stories/supported-data/column.ts create mode 100644 packages/paste-libraries/data-visualization/stories/supported-data/line.ts diff --git a/packages/paste-core/components/chart-provider/src/ChartProvider.tsx b/packages/paste-core/components/chart-provider/src/ChartProvider.tsx index 5404e29284..7e2893f8a4 100644 --- a/packages/paste-core/components/chart-provider/src/ChartProvider.tsx +++ b/packages/paste-core/components/chart-provider/src/ChartProvider.tsx @@ -1,5 +1,7 @@ import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; import type { BoxProps } from "@twilio-paste/box"; +import { transformToHighchartsOptions } from "@twilio-paste/data-visualization-library"; +import type { ChartTypeOptions } from "@twilio-paste/data-visualization-library"; import type { HTMLPasteProps } from "@twilio-paste/types"; import * as Highcharts from "highcharts"; import * as React from "react"; @@ -25,16 +27,47 @@ interface HighchartsOptions extends BaseChartProviderProps { * @memberof ChartProviderProps */ highchartsOptions: Highcharts.Options; - pasteOptions?: never; + options?: never; } -export type ChartProviderProps = HighchartsOptions; +interface ChartOptions extends BaseChartProviderProps { + /** + * Overrides the default element name to apply unique styles with the Customization Provider + * @default null + * @type {BoxProps['element']} + * @memberof ChartProviderProps + */ + highchartsOptions?: never; + options: ChartTypeOptions; +} + +export type ChartProviderProps = HighchartsOptions | ChartOptions; const ChartProvider = React.forwardRef( - ({ element = "CHART_PROVIDER", children, highchartsOptions, ...props }, ref) => { + ({ element = "CHART_PROVIDER", children, highchartsOptions, options, ...props }, ref) => { const [chart, setChart] = React.useState(); const [chartRef, setChartRef] = React.useState(); + if (highchartsOptions && !options) { + return ( + + + {children} + + + ); + } + + const transformedOptions = transformToHighchartsOptions(options); + return ( ( setChart, chartRef, setChartRef, - options: highchartsOptions, + options: transformedOptions, }} > {children} diff --git a/packages/paste-libraries/data-visualization/src/index.tsx b/packages/paste-libraries/data-visualization/src/index.tsx index 3a3b156f7e..6e95fef839 100644 --- a/packages/paste-libraries/data-visualization/src/index.tsx +++ b/packages/paste-libraries/data-visualization/src/index.tsx @@ -1,2 +1,4 @@ export { usePasteHighchartsTheme } from "./usePasteHighchartsTheme"; export { applyPasteHighchartsModules } from "./applyPasteHighchartsModules"; +export { transformToHighchartsOptions } from "./transformers"; +export * from "./types"; diff --git a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts new file mode 100644 index 0000000000..0894ff9dfc --- /dev/null +++ b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts @@ -0,0 +1,78 @@ +import { ThemeContext } from "@twilio-paste/styling-library"; +import { ThemeShape } from "@twilio-paste/theme"; +import React from "react"; + +import { BaseChartOptions } from "../types"; + +export const handleBaseChartOptionsFormatting = ({ + title, + subtitle, + isXTimeAxis, + showLegend = true, + zoomingType, + panningType, + chart, + type, + pointFormatter: userPointFormatter, + ...rest +}: BaseChartOptions): Highcharts.Options => { + const context = React.useContext(ThemeContext) as ThemeShape; + + return { + chart: { + resetZoomButton: { + theme: { + style: { + display: "block", + fontFamily: context.fonts.fontFamilyText, + }, + }, + }, + type, + zoomType: zoomingType || undefined, + panKey: "shift", + panning: { + enabled: Boolean(panningType), + type: panningType, + }, + ...chart, + }, + title: { + text: title?.text, + style: { + display: title?.visible ? "block" : "none", + }, + }, + subtitle: { + text: subtitle?.text, + style: { + display: title?.visible ? "block" : "none", + }, + }, + xAxis: { + type: isXTimeAxis ? "datetime" : undefined, + }, + legend: { + enabled: showLegend, + }, + tooltip: { + backgroundColor: context.backgroundColors.colorBackgroundBodyInverse, + borderColor: context.borderColors.colorBorderInverse, + borderWidth: context.borderWidths.borderWidth10, + borderRadius: context.radii.borderRadius30.replace("px", ""), + padding: 12, + useHTML: Boolean(userPointFormatter), + style: { + fontFamily: context.fonts.fontFamilyText, + color: context.textColors.colorTextInverse, + fontSize: context.fontSizes.fontSize30, + }, + pointFormatter: userPointFormatter + ? function (this) { + return userPointFormatter(this); + } + : undefined, + }, + ...rest, + }; +}; diff --git a/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts b/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts new file mode 100644 index 0000000000..eb622ce6a5 --- /dev/null +++ b/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts @@ -0,0 +1,47 @@ +import Highcharts from "highcharts"; + +import { ColumnChartConfig } from "../types"; +import { handleBaseChartOptionsFormatting } from "./baseFormatter"; + +export const handleColumnOptions = ({ + chart, + series, + type, + stackingType, + xAxisCategories, + showDataLabels, + showStackedLabels, + ...baseChartProps +}: ColumnChartConfig): Highcharts.Options => { + const { xAxis, yAxis, ...rest } = handleBaseChartOptionsFormatting({ + ...baseChartProps, + type, + }); + + return { + series: series.map((s) => ({ ...s, type })), + plotOptions: { + column: { + stacking: stackingType, + dataLabels: { + enabled: showDataLabels, + }, + }, + }, + xAxis: Highcharts.merge( + { + categories: xAxisCategories, + }, + xAxis, + ), + yAxis: Highcharts.merge( + { + stackLabels: { + enabled: showStackedLabels, + }, + }, + yAxis, + ), + ...rest, + }; +}; diff --git a/packages/paste-libraries/data-visualization/src/transformers/index.ts b/packages/paste-libraries/data-visualization/src/transformers/index.ts new file mode 100644 index 0000000000..b1176e21ff --- /dev/null +++ b/packages/paste-libraries/data-visualization/src/transformers/index.ts @@ -0,0 +1,26 @@ +import { ChartTypeOptions, ColumnChartConfig, LineChartConfig } from "../types"; +import { handleBaseChartOptionsFormatting } from "./baseFormatter"; +import { handleColumnOptions } from "./columnChart"; +import { handleLineOptions } from "./lineChart"; + +const handleDefaultOptions = ({ chart, series, type, ...baseChartProps }: ChartTypeOptions): Highcharts.Options => { + return { + // @ts-ignore mentions incompatible types but is correct + series: series.map((s) => ({ ...s, type })), + ...handleBaseChartOptionsFormatting({ ...baseChartProps, type }), + }; +}; + +export const transformToHighchartsOptions = (options: ChartTypeOptions): Highcharts.Options => { + switch (options.type) { + case "line": + return handleLineOptions(options as LineChartConfig); + // case "area": + // return handleAreaOptions(options as AreaChartConfig); + case "column": + return handleColumnOptions(options as ColumnChartConfig); + default: { + return handleDefaultOptions(options); + } + } +}; diff --git a/packages/paste-libraries/data-visualization/src/transformers/lineChart.ts b/packages/paste-libraries/data-visualization/src/transformers/lineChart.ts new file mode 100644 index 0000000000..14d3bc779d --- /dev/null +++ b/packages/paste-libraries/data-visualization/src/transformers/lineChart.ts @@ -0,0 +1,28 @@ +import { LineChartConfig } from "../types"; +import { handleBaseChartOptionsFormatting } from "./baseFormatter"; + +export const handleLineOptions = ({ + series, + type, + zoomingType, + panningType, + ...baseChartProps +}: LineChartConfig): Highcharts.Options => { + return { + series: series.map((s) => ({ + ...s, + type, + })), + plotOptions: { + series: { + stickyTracking: false, + }, + }, + ...handleBaseChartOptionsFormatting({ + ...baseChartProps, + type, + zoomingType, + panningType, + }), + }; +}; diff --git a/packages/paste-libraries/data-visualization/src/types.ts b/packages/paste-libraries/data-visualization/src/types.ts new file mode 100644 index 0000000000..bb65b61762 --- /dev/null +++ b/packages/paste-libraries/data-visualization/src/types.ts @@ -0,0 +1,67 @@ +import * as Highcharts from "highcharts"; + +type SupportedCharts = "line" | "column" | "pie" | "donut" | "arc" | "donut-arc" | "area"; + +export type LineSeries = Pick< + Highcharts.SeriesLineOptions, + "data" | "color" | "accessibility" | "dashStyle" | "lineWidth" | "marker" | "name" +>; + +export type AreaSeries = Pick; + +export type ColumnSeries = Pick< + Highcharts.SeriesColumnOptions, + "data" | "color" | "accessibility" | "events" | "name" | "stacking" +>; + +export type PieSeries = Pick; + +export interface ChartConfig extends Pick { + type?: "line"; +} + +export type ChartAccessibilityConfig = Pick; + +interface TitleConfig extends Pick { + visible?: boolean; +} + +export interface BaseChartOptions { + chart?: ChartConfig; + accessibility?: ChartAccessibilityConfig; + title?: TitleConfig; + subtitle?: TitleConfig; + type: SupportedCharts; + isXTimeAxis?: boolean; + showLegend?: boolean; + zoomingType?: Highcharts.ChartOptions["zoomType"]; + panningType?: Highcharts.ChartOptions["zoomType"]; + pointFormatter?: (point: Highcharts.Point) => string; +} + +export interface LineChartConfig extends BaseChartOptions { + series: LineSeries[]; + type: "line"; +} + +export interface ColumnChartConfig extends BaseChartOptions { + series: ColumnSeries[]; + type: "column"; + stackingType?: "normal" | "percent"; + xAxisCategories?: Highcharts.XAxisOptions["categories"]; + showStackedLabels?: boolean; + showDataLabels?: boolean; +} + +export interface PieChartConfig extends BaseChartOptions { + series: PieSeries[]; + showDataLabels?: boolean; + type: "pie" | "donut" | "arc" | "donut-arc"; +} + +export interface AreaChartConfig extends BaseChartOptions { + series: AreaSeries[]; + type: "area"; +} + +export type ChartTypeOptions = LineChartConfig | ColumnChartConfig; diff --git a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx new file mode 100644 index 0000000000..f068df2b4c --- /dev/null +++ b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx @@ -0,0 +1,149 @@ +import type { Meta, StoryFn } from "@storybook/react"; +import { ChartProvider } from "@twilio-paste/chart-provider"; +import { Stack } from "@twilio-paste/stack"; +import * as React from "react"; + +import { ColumnChartConfig } from "../src"; +import { BaseChart } from "./components/BaseChart"; +import { usdEurData } from "./data/usdEurData"; +import { columnChartData } from "./supported-data/column"; +import { lineSeries } from "./supported-data/line"; + +// eslint-disable-next-line import/no-default-export +export default { + title: "Libraries/data-visualization/supported-charts", + parameters: { + chromatic: { disableSnapshot: true }, + a11y: { + // no need to a11y check composition of a11y checked components + disable: true, + }, + }, +} as Meta; + +export const Line: StoryFn = () => { + return ( + + + + + + ); +}; + +export const Column: StoryFn = () => { + return ( + + + + + + ); +}; + +export const LineZoomPanningTimeSeries: StoryFn = () => { + return ( + + + + + + ); +}; + +export const StackedColumn: StoryFn = () => { + return ( + + + + + + + + + ); +}; + +export const StackedColumnSwitchType: StoryFn = () => { + const [stackingType, setStackingType] = React.useState("normal"); + + return ( + + + + + + + ); +}; diff --git a/packages/paste-libraries/data-visualization/stories/supported-data/column.ts b/packages/paste-libraries/data-visualization/stories/supported-data/column.ts new file mode 100644 index 0000000000..aa79df5c64 --- /dev/null +++ b/packages/paste-libraries/data-visualization/stories/supported-data/column.ts @@ -0,0 +1,16 @@ +import { ColumnSeries } from "../../src"; + +export const columnChartData: ColumnSeries[] = [ + { + name: "Apples", + data: [3, 5, 1, 13], + }, + { + name: "Oranges", + data: [14, 8, 8, 12], + }, + { + name: "Pear", + data: [0, 2, 6, 3], + }, +]; diff --git a/packages/paste-libraries/data-visualization/stories/supported-data/line.ts b/packages/paste-libraries/data-visualization/stories/supported-data/line.ts new file mode 100644 index 0000000000..e893a1934a --- /dev/null +++ b/packages/paste-libraries/data-visualization/stories/supported-data/line.ts @@ -0,0 +1,24 @@ +import { LineSeries } from "../../src"; + +export const lineSeries: LineSeries[] = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + }, + { + name: "Sales & Distribution", + data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387], + }, + { + name: "Project Development", + data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227], + }, + { + name: "Other", + data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111], + }, +]; From ffc2426cf5470e9d41ccd88eed26c9f831a591ea Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 22 Apr 2025 13:53:17 -0500 Subject: [PATCH 25/54] feat(data-visualization): axis titles --- .../src/transformers/baseFormatter.ts | 29 +++++++++++++++++-- .../data-visualization/src/types.ts | 5 +++- .../stories/supported-charts.stories.tsx | 13 ++++----- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts index 0894ff9dfc..589eb8baa3 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts @@ -13,7 +13,10 @@ export const handleBaseChartOptionsFormatting = ({ panningType, chart, type, + yAxisTitle, + xAxisTitle, pointFormatter: userPointFormatter, + enableCredits = false, ...rest }: BaseChartOptions): Highcharts.Options => { const context = React.useContext(ThemeContext) as ThemeShape; @@ -40,17 +43,31 @@ export const handleBaseChartOptionsFormatting = ({ title: { text: title?.text, style: { - display: title?.visible ? "block" : "none", + display: title?.hide ? "none" : "block", }, }, subtitle: { text: subtitle?.text, style: { - display: title?.visible ? "block" : "none", + display: title?.hide ? "none" : "block", }, }, xAxis: { type: isXTimeAxis ? "datetime" : undefined, + title: { + text: xAxisTitle?.text, + style: { + display: xAxisTitle?.hide ? "none" : "block", + }, + }, + }, + yAxis: { + title: { + text: yAxisTitle?.text, + style: { + display: yAxisTitle?.hide ? "none" : "block", + }, + }, }, legend: { enabled: showLegend, @@ -73,6 +90,14 @@ export const handleBaseChartOptionsFormatting = ({ } : undefined, }, + credits: { + enabled: enableCredits, + style: { + fontFamily: context.fonts.fontFamilyText, + color: context.textColors.colorTextWeak, + fontSize: context.fontSizes.fontSize10, + }, + }, ...rest, }; }; diff --git a/packages/paste-libraries/data-visualization/src/types.ts b/packages/paste-libraries/data-visualization/src/types.ts index bb65b61762..786cc8e8d5 100644 --- a/packages/paste-libraries/data-visualization/src/types.ts +++ b/packages/paste-libraries/data-visualization/src/types.ts @@ -23,7 +23,7 @@ export interface ChartConfig extends Pick; interface TitleConfig extends Pick { - visible?: boolean; + hide?: boolean; } export interface BaseChartOptions { @@ -37,6 +37,9 @@ export interface BaseChartOptions { zoomingType?: Highcharts.ChartOptions["zoomType"]; panningType?: Highcharts.ChartOptions["zoomType"]; pointFormatter?: (point: Highcharts.Point) => string; + yAxisTitle?: TitleConfig; + xAxisTitle?: TitleConfig; + enableCredits?: boolean; } export interface LineChartConfig extends BaseChartOptions { diff --git a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx index f068df2b4c..52cbfd5fdd 100644 --- a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx +++ b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx @@ -29,7 +29,6 @@ export const Line: StoryFn = () => { type: "line", series: lineSeries, title: { - visible: true, text: "Solar Employment Growth by Sector, 2010-2016", }, }} @@ -48,7 +47,6 @@ export const Column: StoryFn = () => { type: "column", series: columnChartData, title: { - visible: true, text: "Fruit popularity", }, }} @@ -67,16 +65,20 @@ export const LineZoomPanningTimeSeries: StoryFn = () => { type: "line", series: [{ data: usdEurData, name: "USD to EUR" }], title: { - visible: true, text: "USD to EUR exchange rate", }, subtitle: { - visible: true, text: "Zooming and panning enabled - use drag to zoom and shift+drag to pan", }, isXTimeAxis: true, zoomingType: "xy", panningType: "xy", + xAxisTitle: { + text: "Date", + }, + yAxisTitle: { + text: "Exchange rate", + }, }} > @@ -93,7 +95,6 @@ export const StackedColumn: StoryFn = () => { type: "column", series: columnChartData, title: { - visible: true, text: "Fruit popularity - percent", }, stackingType: "percent", @@ -106,7 +107,6 @@ export const StackedColumn: StoryFn = () => { type: "column", series: columnChartData, title: { - visible: true, text: "Fruit popularity - normal", }, stackingType: "normal", @@ -136,7 +136,6 @@ export const StackedColumnSwitchType: StoryFn = () => { type: "column", series: columnChartData, title: { - visible: true, text: "Fruit popularity", }, stackingType: stackingType, From 984f0b206e91793aaab6fccf0f84f93ca39f68ff Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 22 Apr 2025 14:02:05 -0500 Subject: [PATCH 26/54] feat(data-visualization): include area chart --- .../src/transformers/areaChart.ts | 28 +++++++++++++++++++ .../src/transformers/index.ts | 7 +++-- .../data-visualization/src/types.ts | 25 ++++++++--------- .../stories/supported-charts.stories.tsx | 18 ++++++++++++ 4 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 packages/paste-libraries/data-visualization/src/transformers/areaChart.ts diff --git a/packages/paste-libraries/data-visualization/src/transformers/areaChart.ts b/packages/paste-libraries/data-visualization/src/transformers/areaChart.ts new file mode 100644 index 0000000000..406c18fd9d --- /dev/null +++ b/packages/paste-libraries/data-visualization/src/transformers/areaChart.ts @@ -0,0 +1,28 @@ +import { AreaChartConfig } from "../types"; +import { handleBaseChartOptionsFormatting } from "./baseFormatter"; + +export const handleAreaOptions = ({ + series, + type, + zoomingType, + panningType, + ...baseChartProps +}: AreaChartConfig): Highcharts.Options => { + return { + series: series.map((s) => ({ + ...s, + type, + })), + plotOptions: { + series: { + stickyTracking: false, + }, + }, + ...handleBaseChartOptionsFormatting({ + ...baseChartProps, + type, + zoomingType, + panningType, + }), + }; +}; diff --git a/packages/paste-libraries/data-visualization/src/transformers/index.ts b/packages/paste-libraries/data-visualization/src/transformers/index.ts index b1176e21ff..953bc5ffcb 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/index.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/index.ts @@ -1,4 +1,5 @@ -import { ChartTypeOptions, ColumnChartConfig, LineChartConfig } from "../types"; +import { AreaChartConfig, ChartTypeOptions, ColumnChartConfig, LineChartConfig } from "../types"; +import { handleAreaOptions } from "./areaChart"; import { handleBaseChartOptionsFormatting } from "./baseFormatter"; import { handleColumnOptions } from "./columnChart"; import { handleLineOptions } from "./lineChart"; @@ -15,8 +16,8 @@ export const transformToHighchartsOptions = (options: ChartTypeOptions): Highcha switch (options.type) { case "line": return handleLineOptions(options as LineChartConfig); - // case "area": - // return handleAreaOptions(options as AreaChartConfig); + case "area": + return handleAreaOptions(options as AreaChartConfig); case "column": return handleColumnOptions(options as ColumnChartConfig); default: { diff --git a/packages/paste-libraries/data-visualization/src/types.ts b/packages/paste-libraries/data-visualization/src/types.ts index 786cc8e8d5..2895d719d9 100644 --- a/packages/paste-libraries/data-visualization/src/types.ts +++ b/packages/paste-libraries/data-visualization/src/types.ts @@ -1,24 +1,29 @@ import * as Highcharts from "highcharts"; -type SupportedCharts = "line" | "column" | "pie" | "donut" | "arc" | "donut-arc" | "area"; +type SupportedCharts = "line" | "column" | "area"; +/** + * The object structure required for use as a `series` prop in a chart with the type `line`. + */ export type LineSeries = Pick< Highcharts.SeriesLineOptions, "data" | "color" | "accessibility" | "dashStyle" | "lineWidth" | "marker" | "name" >; +/** + * The object structure required for use as a `series` prop in a chart with the type `area`. + */ export type AreaSeries = Pick; +/** + * The object structure required for use as a `series` prop in a chart with the type `column`. + */ export type ColumnSeries = Pick< Highcharts.SeriesColumnOptions, "data" | "color" | "accessibility" | "events" | "name" | "stacking" >; -export type PieSeries = Pick; - -export interface ChartConfig extends Pick { - type?: "line"; -} +type ChartConfig = Pick; export type ChartAccessibilityConfig = Pick; @@ -56,15 +61,9 @@ export interface ColumnChartConfig extends BaseChartOptions { showDataLabels?: boolean; } -export interface PieChartConfig extends BaseChartOptions { - series: PieSeries[]; - showDataLabels?: boolean; - type: "pie" | "donut" | "arc" | "donut-arc"; -} - export interface AreaChartConfig extends BaseChartOptions { series: AreaSeries[]; type: "area"; } -export type ChartTypeOptions = LineChartConfig | ColumnChartConfig; +export type ChartTypeOptions = LineChartConfig | ColumnChartConfig | AreaChartConfig; diff --git a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx index 52cbfd5fdd..ed130a2c4e 100644 --- a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx +++ b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx @@ -146,3 +146,21 @@ export const StackedColumnSwitchType: StoryFn = () => { ); }; + +export const Area: StoryFn = () => { + return ( + + + + + + ); +}; From d3e2144cce2f9e22e374874e4c22b0b1427a01f4 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 23 Apr 2025 12:41:33 -0500 Subject: [PATCH 27/54] feat(data-visualization): additional example --- .../stories/supported-charts.stories.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx index ed130a2c4e..e77ae43534 100644 --- a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx +++ b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx @@ -57,6 +57,25 @@ export const Column: StoryFn = () => { ); }; +export const ColumnDefinedXAxisCategories: StoryFn = () => { + return ( + + + + + + ); +}; + export const LineZoomPanningTimeSeries: StoryFn = () => { return ( From 718e80c959d7b23ce3ad48c99a2dbf32b376fa72 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 23 Apr 2025 13:15:04 -0500 Subject: [PATCH 28/54] feat(data-visualization): tests --- .../__test__/transformers/areaChart.spec.tsx | 56 ++++ .../transformers/baseFormatter.spec.tsx | 279 ++++++++++++++++++ .../transformers/columnChart.spec.tsx | 109 +++++++ .../__test__/transformers/lineChart.spec.tsx | 56 ++++ 4 files changed, 500 insertions(+) create mode 100644 packages/paste-libraries/data-visualization/__test__/transformers/areaChart.spec.tsx create mode 100644 packages/paste-libraries/data-visualization/__test__/transformers/baseFormatter.spec.tsx create mode 100644 packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx create mode 100644 packages/paste-libraries/data-visualization/__test__/transformers/lineChart.spec.tsx diff --git a/packages/paste-libraries/data-visualization/__test__/transformers/areaChart.spec.tsx b/packages/paste-libraries/data-visualization/__test__/transformers/areaChart.spec.tsx new file mode 100644 index 0000000000..db28e80b72 --- /dev/null +++ b/packages/paste-libraries/data-visualization/__test__/transformers/areaChart.spec.tsx @@ -0,0 +1,56 @@ +import { renderHook } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import React from "react"; + +import { AreaChartConfig, AreaSeries } from "../../src"; +import { handleAreaOptions } from "../../src/transformers/areaChart"; + +const container: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + {children} +); + +const seriesData: AreaSeries[] = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + }, +]; + +const options: AreaChartConfig = { + series: seriesData, + type: "area", +}; + +describe("Area Chart Transformer", () => { + it("should transform area chart data correctly", () => { + const { result } = renderHook(() => handleAreaOptions(options), { wrapper: container }); + + expect(result.current.chart).toEqual( + expect.objectContaining({ + type: "area", + }), + ); + + expect(result.current.plotOptions).toEqual( + expect.objectContaining({ + series: { + stickyTracking: false, + }, + }), + ); + + expect(result.current.series).toEqual( + expect.arrayContaining([ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + type: "area", + }, + ]), + ); + }); +}); diff --git a/packages/paste-libraries/data-visualization/__test__/transformers/baseFormatter.spec.tsx b/packages/paste-libraries/data-visualization/__test__/transformers/baseFormatter.spec.tsx new file mode 100644 index 0000000000..3432639829 --- /dev/null +++ b/packages/paste-libraries/data-visualization/__test__/transformers/baseFormatter.spec.tsx @@ -0,0 +1,279 @@ +import { renderHook } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import React from "react"; + +import { LineChartConfig, LineSeries } from "../../src"; +import { handleBaseChartOptionsFormatting } from "../../src/transformers/baseFormatter"; + +const container: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + {children} +); + +const seriesData: LineSeries[] = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + }, +]; + +const options: LineChartConfig = { + series: seriesData, + type: "line", + title: { + text: "Solar Employment Growth by Sector, 2010-2016", + }, + subtitle: { + text: "Source: thesolarfoundation.com", + }, + xAxisTitle: { + text: "X Axis Title", + }, + yAxisTitle: { + text: "Y Axis Title", + }, +}; + +const mockFormatter = jest.fn(); + +describe("Base Transformer", () => { + it("should show title and sub title if not hidden", () => { + const { result } = renderHook(() => handleBaseChartOptionsFormatting(options), { wrapper: container }); + + expect(result.current.title).toEqual( + expect.objectContaining({ + text: options.title?.text, + style: { + display: "block", + }, + }), + ); + expect(result.current.subtitle).toEqual( + expect.objectContaining({ + text: options.subtitle?.text, + style: { + display: "block", + }, + }), + ); + }); + + it("should hide title and sub title if not hidden", () => { + const { result } = renderHook( + () => + handleBaseChartOptionsFormatting({ + ...options, + title: { ...options.title, hide: true }, + subtitle: { ...options.subtitle, hide: true }, + }), + { wrapper: container }, + ); + + expect(result.current.title).toEqual( + expect.objectContaining({ + text: options.title?.text, + style: { + display: "none", + }, + }), + ); + expect(result.current.subtitle).toEqual( + expect.objectContaining({ + text: options.subtitle?.text, + style: { + display: "none", + }, + }), + ); + }); + + it("should show axis titles if set", () => { + const { result } = renderHook(() => handleBaseChartOptionsFormatting(options), { wrapper: container }); + + expect(result.current.xAxis).toEqual( + expect.objectContaining({ + type: undefined, + title: { + text: options.xAxisTitle?.text, + style: { + display: "block", + }, + }, + }), + ); + + expect(result.current.yAxis).toEqual( + expect.objectContaining({ + title: { + text: options.yAxisTitle?.text, + style: { + display: "block", + }, + }, + }), + ); + }); + + it("should set xAxis type to datetime if isXTimeAxis is true", () => { + const { result } = renderHook( + () => + handleBaseChartOptionsFormatting({ + ...options, + isXTimeAxis: true, + }), + { wrapper: container }, + ); + + expect(result.current.xAxis).toEqual( + expect.objectContaining({ + type: "datetime", + }), + ); + }); + + it("should show legend by default", () => { + const { result } = renderHook(() => handleBaseChartOptionsFormatting(options), { wrapper: container }); + + expect(result.current.legend).toEqual( + expect.objectContaining({ + enabled: true, + }), + ); + }); + + it("should hide legend if showLegend is false", () => { + const { result } = renderHook( + () => + handleBaseChartOptionsFormatting({ + ...options, + showLegend: false, + }), + { wrapper: container }, + ); + + expect(result.current.legend).toEqual( + expect.objectContaining({ + enabled: false, + }), + ); + }); + + it("should hide credits by default", () => { + const { result } = renderHook(() => handleBaseChartOptionsFormatting(options), { wrapper: container }); + + expect(result.current.credits).toEqual( + expect.objectContaining({ + enabled: false, + }), + ); + }); + + it("should show credits if enableCredits is true", () => { + const { result } = renderHook( + () => + handleBaseChartOptionsFormatting({ + ...options, + enableCredits: true, + }), + { wrapper: container }, + ); + + expect(result.current.credits).toEqual( + expect.objectContaining({ + enabled: true, + }), + ); + }); + + it("should not override point formats if not set", () => { + const { result } = renderHook(() => handleBaseChartOptionsFormatting(options), { wrapper: container }); + + expect(result.current.tooltip?.pointFormatter).toBeUndefined(); + }); + + it("should override point formats if set", () => { + const { result } = renderHook( + () => + handleBaseChartOptionsFormatting({ + ...options, + pointFormatter: mockFormatter, + }), + { wrapper: container }, + ); + + expect(result.current.tooltip?.pointFormatter).toBeTruthy(); + // @ts-ignore complains point isn't correct format but not needed in this instance + result.current.tooltip?.pointFormatter?.call({ x: 50 }); + expect(mockFormatter).toHaveBeenCalled(); + expect(mockFormatter).toHaveBeenCalledWith({ x: 50 }); + }); + + it("should set chart type correctly", () => { + const { result } = renderHook(() => handleBaseChartOptionsFormatting(options), { wrapper: container }); + + expect(result.current.chart).toEqual( + expect.objectContaining({ + type: "line", + }), + ); + }); + + it("should not set Zooming type if not set", () => { + const { result } = renderHook(() => handleBaseChartOptionsFormatting(options), { wrapper: container }); + + expect(result.current.chart).toEqual( + expect.objectContaining({ + zoomType: undefined, + }), + ); + }); + + it("should set zoomingType correctly", () => { + const { result } = renderHook( + () => + handleBaseChartOptionsFormatting({ + ...options, + zoomingType: "x", + }), + { wrapper: container }, + ); + + expect(result.current.chart).toEqual( + expect.objectContaining({ + zoomType: "x", + }), + ); + }); + + it("should not set panning if not set", () => { + const { result } = renderHook(() => handleBaseChartOptionsFormatting(options), { wrapper: container }); + + expect(result.current.chart?.panning).toEqual( + expect.objectContaining({ + enabled: false, + type: undefined, + }), + ); + }); + + it("should set panning correctly", () => { + const { result } = renderHook( + () => + handleBaseChartOptionsFormatting({ + ...options, + panningType: "x", + }), + { wrapper: container }, + ); + + expect(result.current.chart?.panning).toEqual( + expect.objectContaining({ + enabled: true, + type: "x", + }), + ); + }); +}); diff --git a/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx b/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx new file mode 100644 index 0000000000..f6e541dade --- /dev/null +++ b/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx @@ -0,0 +1,109 @@ +import { renderHook } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import React from "react"; + +import { ColumnChartConfig, ColumnSeries } from "../../src"; +import { handleColumnOptions } from "../../src/transformers/columnChart"; + +const container: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + {children} +); + +const seriesData: ColumnSeries[] = [ + { + name: "Apples", + data: [3, 5, 1, 13], + }, + { + name: "Oranges", + data: [14, 8, 8, 12], + }, +]; + +const options: ColumnChartConfig = { + series: seriesData, + type: "column", +}; + +describe("Column Chart Transformer", () => { + it("should transform column chart data correctly with only required props", () => { + const { result } = renderHook(() => handleColumnOptions(options), { wrapper: container }); + + expect(result.current.plotOptions?.column).toEqual( + expect.objectContaining({ + stacking: undefined, + dataLabels: { + enabled: undefined, + }, + }), + ); + + expect(result.current.chart).toEqual( + expect.objectContaining({ + type: "column", + }), + ); + + expect(result.current.xAxis).toEqual( + expect.objectContaining({ + categories: undefined, + }), + ); + + expect(result.current.yAxis).toEqual( + expect.objectContaining({ + stackLabels: { + enabled: undefined, + }, + }), + ); + + expect(result.current.series).toEqual( + expect.arrayContaining([ + { + name: "Apples", + data: [3, 5, 1, 13], + type: "column", + }, + ]), + ); + }); + + it("should transform column chart data correctly with only required props", () => { + const xAxisCategories = ["2020", "2021", "2022", "2023"]; + const { result } = renderHook( + () => + handleColumnOptions({ + ...options, + xAxisCategories, + stackingType: "normal", + showStackedLabels: true, + showDataLabels: true, + }), + { wrapper: container }, + ); + + expect(result.current.plotOptions?.column).toEqual( + expect.objectContaining({ + stacking: "normal", + dataLabels: { + enabled: true, + }, + }), + ); + + expect(result.current.xAxis).toEqual( + expect.objectContaining({ + categories: xAxisCategories, + }), + ); + + expect(result.current.yAxis).toEqual( + expect.objectContaining({ + stackLabels: { + enabled: true, + }, + }), + ); + }); +}); diff --git a/packages/paste-libraries/data-visualization/__test__/transformers/lineChart.spec.tsx b/packages/paste-libraries/data-visualization/__test__/transformers/lineChart.spec.tsx new file mode 100644 index 0000000000..a49d749dfb --- /dev/null +++ b/packages/paste-libraries/data-visualization/__test__/transformers/lineChart.spec.tsx @@ -0,0 +1,56 @@ +import { renderHook } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import React from "react"; + +import { LineChartConfig, LineSeries } from "../../src"; +import { handleLineOptions } from "../../src/transformers/lineChart"; + +const container: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + {children} +); + +const seriesData: LineSeries[] = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + }, +]; + +const options: LineChartConfig = { + series: seriesData, + type: "line", +}; + +describe("Line Chart Transformer", () => { + it("should transform line chart data correctly", () => { + const { result } = renderHook(() => handleLineOptions(options), { wrapper: container }); + + expect(result.current.chart).toEqual( + expect.objectContaining({ + type: "line", + }), + ); + + expect(result.current.plotOptions).toEqual( + expect.objectContaining({ + series: { + stickyTracking: false, + }, + }), + ); + + expect(result.current.series).toEqual( + expect.arrayContaining([ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + type: "line", + }, + ]), + ); + }); +}); From 4ef5467f8a2c42fdeca96e36d1bea19692a155a2 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 23 Apr 2025 13:41:36 -0500 Subject: [PATCH 29/54] feat(data-visualization): refactor --- .../data-visualization/src/transformers/baseFormatter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts index 589eb8baa3..7a83ddde64 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts @@ -32,7 +32,7 @@ export const handleBaseChartOptionsFormatting = ({ }, }, type, - zoomType: zoomingType || undefined, + zoomType: zoomingType, panKey: "shift", panning: { enabled: Boolean(panningType), From 4c6b80dba32604926bf799e71544e2dd01ba71c8 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 23 Apr 2025 16:10:19 -0500 Subject: [PATCH 30/54] chore(data-visualization): lci checks --- packages/paste-core/components/chart-provider/package.json | 1 + .../__test__/transformers/baseFormatter.spec.tsx | 1 + .../__test__/transformers/columnChart.spec.tsx | 2 +- .../data-visualization/src/transformers/index.ts | 1 + .../data-visualization/stories/supported-charts.stories.tsx | 2 +- yarn.lock | 1 + 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/paste-core/components/chart-provider/package.json b/packages/paste-core/components/chart-provider/package.json index 13c9220263..375371ac14 100644 --- a/packages/paste-core/components/chart-provider/package.json +++ b/packages/paste-core/components/chart-provider/package.json @@ -29,6 +29,7 @@ "@twilio-paste/box": "^11.0.0", "@twilio-paste/color-contrast-utils": "^5.0.0", "@twilio-paste/customization": "^9.0.0", + "@twilio-paste/data-visualization-library": "^6.0.1", "@twilio-paste/design-tokens": "^10.3.0", "@twilio-paste/style-props": "^10.0.0", "@twilio-paste/styling-library": "^4.0.0", diff --git a/packages/paste-libraries/data-visualization/__test__/transformers/baseFormatter.spec.tsx b/packages/paste-libraries/data-visualization/__test__/transformers/baseFormatter.spec.tsx index 3432639829..de7110e685 100644 --- a/packages/paste-libraries/data-visualization/__test__/transformers/baseFormatter.spec.tsx +++ b/packages/paste-libraries/data-visualization/__test__/transformers/baseFormatter.spec.tsx @@ -205,6 +205,7 @@ describe("Base Transformer", () => { ); expect(result.current.tooltip?.pointFormatter).toBeTruthy(); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore complains point isn't correct format but not needed in this instance result.current.tooltip?.pointFormatter?.call({ x: 50 }); expect(mockFormatter).toHaveBeenCalled(); diff --git a/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx b/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx index f6e541dade..b492a74e5b 100644 --- a/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx +++ b/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx @@ -69,7 +69,7 @@ describe("Column Chart Transformer", () => { ); }); - it("should transform column chart data correctly with only required props", () => { + it("should transform column chart data correctly with optional props", () => { const xAxisCategories = ["2020", "2021", "2022", "2023"]; const { result } = renderHook( () => diff --git a/packages/paste-libraries/data-visualization/src/transformers/index.ts b/packages/paste-libraries/data-visualization/src/transformers/index.ts index 953bc5ffcb..2572a0dcf4 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/index.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/index.ts @@ -6,6 +6,7 @@ import { handleLineOptions } from "./lineChart"; const handleDefaultOptions = ({ chart, series, type, ...baseChartProps }: ChartTypeOptions): Highcharts.Options => { return { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore mentions incompatible types but is correct series: series.map((s) => ({ ...s, type })), ...handleBaseChartOptionsFormatting({ ...baseChartProps, type }), diff --git a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx index e77ae43534..a905e286fb 100644 --- a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx +++ b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx @@ -157,7 +157,7 @@ export const StackedColumnSwitchType: StoryFn = () => { title: { text: "Fruit popularity", }, - stackingType: stackingType, + stackingType, }} > diff --git a/yarn.lock b/yarn.lock index 62fc01cb97..a0eeb9fab6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11530,6 +11530,7 @@ __metadata: "@twilio-paste/box": ^11.0.0 "@twilio-paste/color-contrast-utils": ^5.0.0 "@twilio-paste/customization": ^9.0.0 + "@twilio-paste/data-visualization-library": ^6.0.1 "@twilio-paste/design-tokens": ^10.3.0 "@twilio-paste/style-props": ^10.0.0 "@twilio-paste/styling-library": ^4.0.0 From d5169fc53ac972c1f279be06c3d7fabc80fdbb15 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 23 Apr 2025 16:17:55 -0500 Subject: [PATCH 31/54] feat(data-visualization): changesets --- .changeset/serious-avocados-stare.md | 6 ++++++ .changeset/twenty-rocks-tease.md | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 .changeset/serious-avocados-stare.md create mode 100644 .changeset/twenty-rocks-tease.md diff --git a/.changeset/serious-avocados-stare.md b/.changeset/serious-avocados-stare.md new file mode 100644 index 0000000000..52152ac07c --- /dev/null +++ b/.changeset/serious-avocados-stare.md @@ -0,0 +1,6 @@ +--- +"@twilio-paste/core": minor +"@twilio-paste/data-visualization-library": minor +--- + +[Data visualization library] added helper functions and types to provide support for creating highcharts options for supported chart types diff --git a/.changeset/twenty-rocks-tease.md b/.changeset/twenty-rocks-tease.md new file mode 100644 index 0000000000..0b933bb27e --- /dev/null +++ b/.changeset/twenty-rocks-tease.md @@ -0,0 +1,6 @@ +--- +"@twilio-paste/chart-provider": minor +"@twilio-paste/core": minor +--- + +[Chart Provider] added the ability to use options for supported chart types From c25b041f47a1527a12517a63f5fab7161519b29e Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Thu, 24 Apr 2025 10:25:06 -0500 Subject: [PATCH 32/54] feat(data-visualization): animation boolean --- .../data-visualization/src/transformers/baseFormatter.ts | 2 ++ packages/paste-libraries/data-visualization/src/types.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts index 7a83ddde64..e1202c5e8a 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts @@ -17,6 +17,7 @@ export const handleBaseChartOptionsFormatting = ({ xAxisTitle, pointFormatter: userPointFormatter, enableCredits = false, + isAnimated = true, ...rest }: BaseChartOptions): Highcharts.Options => { const context = React.useContext(ThemeContext) as ThemeShape; @@ -38,6 +39,7 @@ export const handleBaseChartOptionsFormatting = ({ enabled: Boolean(panningType), type: panningType, }, + animation: isAnimated, ...chart, }, title: { diff --git a/packages/paste-libraries/data-visualization/src/types.ts b/packages/paste-libraries/data-visualization/src/types.ts index 2895d719d9..aaa8a6c2a1 100644 --- a/packages/paste-libraries/data-visualization/src/types.ts +++ b/packages/paste-libraries/data-visualization/src/types.ts @@ -45,6 +45,7 @@ export interface BaseChartOptions { yAxisTitle?: TitleConfig; xAxisTitle?: TitleConfig; enableCredits?: boolean; + isAnimated?: boolean; } export interface LineChartConfig extends BaseChartOptions { From 26c20bc0a99597cd0a6c50dca2e248e28849b689 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Fri, 25 Apr 2025 09:31:43 -0500 Subject: [PATCH 33/54] feat(data-visualization): wip --- .../components/chart-provider/package.json | 1 + .../src/transformers/baseFormatter.ts | 4 +- .../src/transformers/columnChart.ts | 6 - .../data-visualization/src/types.ts | 5 +- .../stories/supported-charts.stories.tsx | 1 + .../data-visualization/BaseChart.tsx | 4 +- .../data-visualization/ChartExamples.ts | 340 ++ .../ChartProviderExamples.ts | 57 - .../data-visualization/usdEurData.ts | 2844 +++++++++++++++++ .../pages/components/chart-provider/index.mdx | 38 +- .../engineering/chart-types.mdx | 96 +- 11 files changed, 3326 insertions(+), 70 deletions(-) create mode 100644 packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts delete mode 100644 packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts create mode 100644 packages/paste-website/src/component-examples/data-visualization/usdEurData.ts diff --git a/packages/paste-core/components/chart-provider/package.json b/packages/paste-core/components/chart-provider/package.json index 375371ac14..b4c6a092e8 100644 --- a/packages/paste-core/components/chart-provider/package.json +++ b/packages/paste-core/components/chart-provider/package.json @@ -46,6 +46,7 @@ "@twilio-paste/box": "^11.0.1", "@twilio-paste/color-contrast-utils": "^5.0.0", "@twilio-paste/customization": "^9.0.1", + "@twilio-paste/data-visualization-library": "^6.0.1", "@twilio-paste/design-tokens": "^10.13.0", "@twilio-paste/style-props": "^10.0.1", "@twilio-paste/styling-library": "^4.0.1", diff --git a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts index e1202c5e8a..7f866e012c 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/baseFormatter.ts @@ -15,6 +15,7 @@ export const handleBaseChartOptionsFormatting = ({ type, yAxisTitle, xAxisTitle, + xAxisCategories, pointFormatter: userPointFormatter, enableCredits = false, isAnimated = true, @@ -62,6 +63,7 @@ export const handleBaseChartOptionsFormatting = ({ display: xAxisTitle?.hide ? "none" : "block", }, }, + categories: xAxisCategories, }, yAxis: { title: { @@ -78,7 +80,7 @@ export const handleBaseChartOptionsFormatting = ({ backgroundColor: context.backgroundColors.colorBackgroundBodyInverse, borderColor: context.borderColors.colorBorderInverse, borderWidth: context.borderWidths.borderWidth10, - borderRadius: context.radii.borderRadius30.replace("px", ""), + borderRadius: context.radii.borderRadius30?.replace("px", ""), padding: 12, useHTML: Boolean(userPointFormatter), style: { diff --git a/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts b/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts index eb622ce6a5..125b817542 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts @@ -28,12 +28,6 @@ export const handleColumnOptions = ({ }, }, }, - xAxis: Highcharts.merge( - { - categories: xAxisCategories, - }, - xAxis, - ), yAxis: Highcharts.merge( { stackLabels: { diff --git a/packages/paste-libraries/data-visualization/src/types.ts b/packages/paste-libraries/data-visualization/src/types.ts index aaa8a6c2a1..67904c7937 100644 --- a/packages/paste-libraries/data-visualization/src/types.ts +++ b/packages/paste-libraries/data-visualization/src/types.ts @@ -25,12 +25,13 @@ export type ColumnSeries = Pick< type ChartConfig = Pick; -export type ChartAccessibilityConfig = Pick; +type ChartAccessibilityConfig = Pick; interface TitleConfig extends Pick { hide?: boolean; } + export interface BaseChartOptions { chart?: ChartConfig; accessibility?: ChartAccessibilityConfig; @@ -46,6 +47,7 @@ export interface BaseChartOptions { xAxisTitle?: TitleConfig; enableCredits?: boolean; isAnimated?: boolean; + xAxisCategories?: Highcharts.XAxisOptions["categories"]; } export interface LineChartConfig extends BaseChartOptions { @@ -57,7 +59,6 @@ export interface ColumnChartConfig extends BaseChartOptions { series: ColumnSeries[]; type: "column"; stackingType?: "normal" | "percent"; - xAxisCategories?: Highcharts.XAxisOptions["categories"]; showStackedLabels?: boolean; showDataLabels?: boolean; } diff --git a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx index a905e286fb..c0b00016a0 100644 --- a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx +++ b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx @@ -31,6 +31,7 @@ export const Line: StoryFn = () => { title: { text: "Solar Employment Growth by Sector, 2010-2016", }, + isXTimeAxis: true, }} > diff --git a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx index b9ad272c36..82994b5e2c 100644 --- a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx +++ b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx @@ -10,7 +10,9 @@ const Chart: React.FC = () => { applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); const chartRef = React.useRef(null); const { options, setChart, setChartRef } = React.useContext(ChartContext); - const [chartOptions, setChartOptions] = React.useState(usePasteHighchartsTheme(options)); + const [chartOptions, setChartOptions] = React.useState( + Highcharts.merge({ plotOptions: { series: { animation: false } } }, usePasteHighchartsTheme(options)), + ); React.useLayoutEffect(() => { setChartOptions(Highcharts.merge(chartOptions, options)); diff --git a/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts b/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts new file mode 100644 index 0000000000..9c10f44de7 --- /dev/null +++ b/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts @@ -0,0 +1,340 @@ +export const SimpleChartProviderExample = ` +const ChartProviderExample = () => { + const lineSeriesData = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + +export const CustomChartProviderExample = ` +const ChartProviderExample = () => { + const lineSeriesData = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + type: "line", + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + type: "line", + }, + { + name: "Sales & Distribution", + data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387], + type: "column", + }, + { + name: "Project Development", + data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227], + type: "column", + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + +export const DefaultLineExample = ` +const DefaultLineExample = () => { + const lineSeriesData = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + +export const LineTimeSeriesPanZoomExample = ` +const LineTimeSeriesPanZoomExample = () => { + const exampleDataStructure = [ + [1167609600000, 0.7537], + [1167696000000, 0.7537], + [1167782400000, 0.7559], + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + +export const DefaultAreaExample = ` +const DefaultAreaExample = () => { + const areaSeriesData = [ + { + name: "Installation", + data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], + }, + { + name: "Manufacturing", + data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + + +export const AreaTimeSeriesPanZoomExample = ` +const AreaTimeSeriesPanZoomExample = () => { + const exampleDataStructure = [ + [1167609600000, 0.7537], + [1167696000000, 0.7537], + [1167782400000, 0.7559], + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + +export const DefaultColumnExample = ` +const DefaultColumnExample = () => { + const columnSeriesData = [ + { + name: "Apples", + data: [3, 5, 1, 13], + }, + { + name: "Oranges", + data: [14, 8, 8, 12], + }, + { + name: "Pear", + data: [0, 2, 6, 3], + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + +export const ColumnStackedNormalExample = ` +const ColumnStackedNormalExample = () => { + const columnSeriesData = [ + { + name: "Apples", + data: [3, 5, 1, 13], + }, + { + name: "Oranges", + data: [14, 8, 8, 12], + }, + { + name: "Pear", + data: [0, 2, 6, 3], + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + +export const ColumnStackedPercentExample = ` +const ColumnStackedPercentExample = () => { + const columnSeriesData = [ + { + name: "Apples", + data: [3, 5, 1, 13], + }, + { + name: "Oranges", + data: [14, 8, 8, 12], + }, + { + name: "Pear", + data: [0, 2, 6, 3], + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); + + +export const ColumnGroupedAxisExample = ` +const ColumnGroupedAxisExample = () => { + const columnSeriesData = [ + { + name: "Apples", + data: [3, 5, 1, 13], + }, + { + name: "Oranges", + data: [14, 8, 8, 12], + }, + { + name: "Pear", + data: [0, 2, 6, 3], + }, + ] + + return ( + + + + ); +}; + +render(); +`.trim(); \ No newline at end of file diff --git a/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts b/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts deleted file mode 100644 index 461f90b637..0000000000 --- a/packages/paste-website/src/component-examples/data-visualization/ChartProviderExamples.ts +++ /dev/null @@ -1,57 +0,0 @@ -export const SimpleChartProviderExample = ` -const ChartProviderExample = () => { - const lineSeriesData = [ - { - name: "Installation", - data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], - }, - { - name: "Manufacturing", - data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], - }, - ] - - return ( - - - - ); -}; - -render(); -`.trim(); - -export const CustomChartProviderExample = ` -const ChartProviderExample = () => { - const lineSeriesData = [ - { - name: "Installation", - data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], - type: "line", - }, - { - name: "Manufacturing", - data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], - type: "line", - }, - { - name: "Sales & Distribution", - data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387], - type: "column", - }, - { - name: "Project Development", - data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227], - type: "column", - }, - ] - - return ( - - - - ); -}; - -render(); -`.trim(); diff --git a/packages/paste-website/src/component-examples/data-visualization/usdEurData.ts b/packages/paste-website/src/component-examples/data-visualization/usdEurData.ts new file mode 100644 index 0000000000..2bb48f5b31 --- /dev/null +++ b/packages/paste-website/src/component-examples/data-visualization/usdEurData.ts @@ -0,0 +1,2844 @@ +export const usdEurData = [ + [1167609600000, 0.7537], + [1167696000000, 0.7537], + [1167782400000, 0.7559], + [1167868800000, 0.7631], + [1167955200000, 0.7644], + [1168214400000, 0.769], + [1168300800000, 0.7683], + [1168387200000, 0.77], + [1168473600000, 0.7703], + [1168560000000, 0.7757], + [1168819200000, 0.7728], + [1168905600000, 0.7721], + [1168992000000, 0.7748], + [1169078400000, 0.774], + [1169164800000, 0.7718], + [1169424000000, 0.7731], + [1169510400000, 0.767], + [1169596800000, 0.769], + [1169683200000, 0.7706], + [1169769600000, 0.7752], + [1170028800000, 0.774], + [1170115200000, 0.771], + [1170201600000, 0.7721], + [1170288000000, 0.7681], + [1170374400000, 0.7681], + [1170633600000, 0.7738], + [1170720000000, 0.772], + [1170806400000, 0.7701], + [1170892800000, 0.7699], + [1170979200000, 0.7689], + [1171238400000, 0.7719], + [1171324800000, 0.768], + [1171411200000, 0.7645], + [1171497600000, 0.7613], + [1171584000000, 0.7624], + [1171843200000, 0.7616], + [1171929600000, 0.7608], + [1172016000000, 0.7608], + [1172102400000, 0.7631], + [1172188800000, 0.7615], + [1172448000000, 0.76], + [1172534400000, 0.756], + [1172620800000, 0.757], + [1172707200000, 0.7562], + [1172793600000, 0.7598], + [1173052800000, 0.7645], + [1173139200000, 0.7635], + [1173225600000, 0.7614], + [1173312000000, 0.7604], + [1173398400000, 0.7603], + [1173657600000, 0.7602], + [1173744000000, 0.7566], + [1173830400000, 0.7587], + [1173916800000, 0.7562], + [1174003200000, 0.7506], + [1174262400000, 0.7518], + [1174348800000, 0.7522], + [1174435200000, 0.7524], + [1174521600000, 0.7491], + [1174608000000, 0.7505], + [1174867200000, 0.754], + [1174953600000, 0.7493], + [1175040000000, 0.7493], + [1175126400000, 0.7491], + [1175212800000, 0.751], + [1175472000000, 0.7483], + [1175558400000, 0.7487], + [1175644800000, 0.7491], + [1175731200000, 0.7479], + [1175817600000, 0.7479], + [1176076800000, 0.7479], + [1176163200000, 0.7449], + [1176249600000, 0.7454], + [1176336000000, 0.7427], + [1176422400000, 0.7391], + [1176681600000, 0.7381], + [1176768000000, 0.7382], + [1176854400000, 0.7366], + [1176940800000, 0.7353], + [1177027200000, 0.7351], + [1177286400000, 0.7377], + [1177372800000, 0.7364], + [1177459200000, 0.7328], + [1177545600000, 0.7356], + [1177632000000, 0.7331], + [1177891200000, 0.7351], + [1177977600000, 0.7351], + [1178064000000, 0.736], + [1178150400000, 0.7347], + [1178236800000, 0.7375], + [1178496000000, 0.7346], + [1178582400000, 0.7377], + [1178668800000, 0.7389], + [1178755200000, 0.7394], + [1178841600000, 0.7416], + [1179100800000, 0.7382], + [1179187200000, 0.7388], + [1179273600000, 0.7368], + [1179360000000, 0.74], + [1179446400000, 0.7421], + [1179705600000, 0.7439], + [1179792000000, 0.7434], + [1179878400000, 0.7414], + [1179964800000, 0.7437], + [1180051200000, 0.7441], + [1180310400000, 0.7434], + [1180396800000, 0.7403], + [1180483200000, 0.7453], + [1180569600000, 0.7434], + [1180656000000, 0.7444], + [1180915200000, 0.7418], + [1181001600000, 0.7391], + [1181088000000, 0.7401], + [1181174400000, 0.7425], + [1181260800000, 0.7492], + [1181520000000, 0.7489], + [1181606400000, 0.7494], + [1181692800000, 0.7527], + [1181779200000, 0.7518], + [1181865600000, 0.7512], + [1182124800000, 0.7461], + [1182211200000, 0.7462], + [1182297600000, 0.7449], + [1182384000000, 0.7465], + [1182470400000, 0.7441], + [1182729600000, 0.743], + [1182816000000, 0.743], + [1182902400000, 0.7443], + [1182988800000, 0.7427], + [1183075200000, 0.7406], + [1183334400000, 0.736], + [1183420800000, 0.7353], + [1183507200000, 0.7344], + [1183593600000, 0.7332], + [1183680000000, 0.7356], + [1183939200000, 0.7343], + [1184025600000, 0.7318], + [1184112000000, 0.7272], + [1184198400000, 0.7254], + [1184284800000, 0.7257], + [1184544000000, 0.7257], + [1184630400000, 0.7263], + [1184716800000, 0.7258], + [1184803200000, 0.7237], + [1184889600000, 0.7246], + [1185148800000, 0.7236], + [1185235200000, 0.723], + [1185321600000, 0.7277], + [1185408000000, 0.7289], + [1185494400000, 0.7326], + [1185753600000, 0.7322], + [1185840000000, 0.7297], + [1185926400000, 0.732], + [1186012800000, 0.732], + [1186099200000, 0.7303], + [1186358400000, 0.7238], + [1186444800000, 0.7251], + [1186531200000, 0.7251], + [1186617600000, 0.7285], + [1186704000000, 0.7327], + [1186963200000, 0.7326], + [1187049600000, 0.7359], + [1187136000000, 0.7422], + [1187222400000, 0.7461], + [1187308800000, 0.7434], + [1187568000000, 0.7422], + [1187654400000, 0.7404], + [1187740800000, 0.7412], + [1187827200000, 0.7368], + [1187913600000, 0.7346], + [1188172800000, 0.7323], + [1188259200000, 0.732], + [1188345600000, 0.7337], + [1188432000000, 0.7349], + [1188518400000, 0.7298], + [1188777600000, 0.7337], + [1188864000000, 0.7365], + [1188950400000, 0.736], + [1189036800000, 0.7317], + [1189123200000, 0.7302], + [1189382400000, 0.725], + [1189468800000, 0.7235], + [1189555200000, 0.7203], + [1189641600000, 0.7197], + [1189728000000, 0.7216], + [1189987200000, 0.7207], + [1190073600000, 0.7212], + [1190160000000, 0.7157], + [1190246400000, 0.7129], + [1190332800000, 0.7119], + [1190592000000, 0.7087], + [1190678400000, 0.709], + [1190764800000, 0.708], + [1190851200000, 0.7053], + [1190937600000, 0.7054], + [1191196800000, 0.7027], + [1191283200000, 0.7061], + [1191369600000, 0.7046], + [1191456000000, 0.7089], + [1191542400000, 0.7075], + [1191801600000, 0.7099], + [1191888000000, 0.7125], + [1191974400000, 0.707], + [1192060800000, 0.7044], + [1192147200000, 0.7057], + [1192406400000, 0.703], + [1192492800000, 0.7068], + [1192579200000, 0.7043], + [1192665600000, 0.6994], + [1192752000000, 0.7], + [1193011200000, 0.706], + [1193097600000, 0.7017], + [1193184000000, 0.7028], + [1193270400000, 0.699], + [1193356800000, 0.6953], + [1193616000000, 0.695], + [1193702400000, 0.6942], + [1193788800000, 0.6923], + [1193875200000, 0.6934], + [1193961600000, 0.6908], + [1194220800000, 0.6903], + [1194307200000, 0.6875], + [1194393600000, 0.6794], + [1194480000000, 0.6819], + [1194566400000, 0.6812], + [1194825600000, 0.686], + [1194912000000, 0.6847], + [1194998400000, 0.6804], + [1195084800000, 0.6832], + [1195171200000, 0.6826], + [1195430400000, 0.6825], + [1195516800000, 0.6765], + [1195603200000, 0.6751], + [1195689600000, 0.6745], + [1195776000000, 0.6754], + [1196035200000, 0.6737], + [1196121600000, 0.6724], + [1196208000000, 0.6782], + [1196294400000, 0.6786], + [1196380800000, 0.6776], + [1196640000000, 0.6819], + [1196726400000, 0.6785], + [1196812800000, 0.6794], + [1196899200000, 0.6872], + [1196985600000, 0.6827], + [1197244800000, 0.6795], + [1197331200000, 0.6817], + [1197417600000, 0.6815], + [1197504000000, 0.6812], + [1197590400000, 0.6893], + [1197849600000, 0.6949], + [1197936000000, 0.6938], + [1198022400000, 0.6953], + [1198108800000, 0.697], + [1198195200000, 0.6955], + [1198454400000, 0.6946], + [1198540800000, 0.6946], + [1198627200000, 0.6946], + [1198713600000, 0.689], + [1198800000000, 0.6807], + [1199059200000, 0.6794], + [1199145600000, 0.6794], + [1199232000000, 0.6809], + [1199318400000, 0.6779], + [1199404800000, 0.6791], + [1199664000000, 0.6793], + [1199750400000, 0.6801], + [1199836800000, 0.6813], + [1199923200000, 0.6821], + [1200009600000, 0.6761], + [1200268800000, 0.6715], + [1200355200000, 0.6719], + [1200441600000, 0.6761], + [1200528000000, 0.6808], + [1200614400000, 0.6816], + [1200873600000, 0.6906], + [1200960000000, 0.69], + [1201046400000, 0.6863], + [1201132800000, 0.6821], + [1201219200000, 0.6801], + [1201478400000, 0.6778], + [1201564800000, 0.677], + [1201651200000, 0.6753], + [1201737600000, 0.6726], + [1201824000000, 0.6717], + [1202083200000, 0.6745], + [1202169600000, 0.6809], + [1202256000000, 0.684], + [1202342400000, 0.6865], + [1202428800000, 0.6891], + [1202688000000, 0.6878], + [1202774400000, 0.688], + [1202860800000, 0.6857], + [1202947200000, 0.6838], + [1203033600000, 0.6816], + [1203292800000, 0.6833], + [1203379200000, 0.6784], + [1203465600000, 0.6824], + [1203552000000, 0.6787], + [1203638400000, 0.6736], + [1203897600000, 0.675], + [1203984000000, 0.6724], + [1204070400000, 0.6648], + [1204156800000, 0.6614], + [1204243200000, 0.6594], + [1204502400000, 0.6579], + [1204588800000, 0.6577], + [1204675200000, 0.6582], + [1204761600000, 0.6529], + [1204848000000, 0.6487], + [1205107200000, 0.652], + [1205193600000, 0.6503], + [1205280000000, 0.6462], + [1205366400000, 0.6421], + [1205452800000, 0.6427], + [1205712000000, 0.6342], + [1205798400000, 0.6342], + [1205884800000, 0.6374], + [1205971200000, 0.6485], + [1206057600000, 0.6485], + [1206316800000, 0.6485], + [1206403200000, 0.6424], + [1206489600000, 0.6366], + [1206576000000, 0.6336], + [1206662400000, 0.6332], + [1206921600000, 0.6325], + [1207008000000, 0.6387], + [1207094400000, 0.6398], + [1207180800000, 0.6442], + [1207267200000, 0.6362], + [1207526400000, 0.6373], + [1207612800000, 0.6373], + [1207699200000, 0.636], + [1207785600000, 0.63], + [1207872000000, 0.6317], + [1208131200000, 0.6303], + [1208217600000, 0.6319], + [1208304000000, 0.6279], + [1208390400000, 0.6301], + [1208476800000, 0.6338], + [1208736000000, 0.6291], + [1208822400000, 0.6278], + [1208908800000, 0.6275], + [1208995200000, 0.6343], + [1209081600000, 0.6413], + [1209340800000, 0.64], + [1209427200000, 0.6423], + [1209513600000, 0.6436], + [1209600000000, 0.6436], + [1209686400000, 0.647], + [1209945600000, 0.6469], + [1210032000000, 0.6441], + [1210118400000, 0.6482], + [1210204800000, 0.6517], + [1210291200000, 0.647], + [1210550400000, 0.6482], + [1210636800000, 0.6464], + [1210723200000, 0.6478], + [1210809600000, 0.6463], + [1210896000000, 0.6453], + [1211155200000, 0.6421], + [1211241600000, 0.6395], + [1211328000000, 0.6349], + [1211414400000, 0.6348], + [1211500800000, 0.6353], + [1211760000000, 0.6346], + [1211846400000, 0.6346], + [1211932800000, 0.6388], + [1212019200000, 0.6431], + [1212105600000, 0.6449], + [1212364800000, 0.6444], + [1212451200000, 0.6414], + [1212537600000, 0.6467], + [1212624000000, 0.6494], + [1212710400000, 0.6412], + [1212969600000, 0.6337], + [1213056000000, 0.6442], + [1213142400000, 0.6446], + [1213228800000, 0.6487], + [1213315200000, 0.6522], + [1213574400000, 0.647], + [1213660800000, 0.6462], + [1213747200000, 0.6456], + [1213833600000, 0.6461], + [1213920000000, 0.6407], + [1214179200000, 0.6444], + [1214265600000, 0.6424], + [1214352000000, 0.6412], + [1214438400000, 0.6358], + [1214524800000, 0.6351], + [1214784000000, 0.6345], + [1214870400000, 0.634], + [1214956800000, 0.6328], + [1215043200000, 0.6296], + [1215129600000, 0.6382], + [1215388800000, 0.639], + [1215475200000, 0.6376], + [1215561600000, 0.6364], + [1215648000000, 0.6367], + [1215734400000, 0.6316], + [1215993600000, 0.6311], + [1216080000000, 0.6255], + [1216166400000, 0.6295], + [1216252800000, 0.6311], + [1216339200000, 0.6324], + [1216598400000, 0.6307], + [1216684800000, 0.6283], + [1216771200000, 0.6354], + [1216857600000, 0.638], + [1216944000000, 0.6357], + [1217203200000, 0.6352], + [1217289600000, 0.6368], + [1217376000000, 0.6416], + [1217462400000, 0.6407], + [1217548800000, 0.6422], + [1217808000000, 0.6425], + [1217894400000, 0.6458], + [1217980800000, 0.6462], + [1218067200000, 0.6465], + [1218153600000, 0.6635], + [1218412800000, 0.6662], + [1218499200000, 0.6709], + [1218585600000, 0.6711], + [1218672000000, 0.6709], + [1218758400000, 0.679], + [1219017600000, 0.6802], + [1219104000000, 0.6814], + [1219190400000, 0.6788], + [1219276800000, 0.6751], + [1219363200000, 0.6754], + [1219622400000, 0.6773], + [1219708800000, 0.6851], + [1219795200000, 0.6773], + [1219881600000, 0.6771], + [1219968000000, 0.6788], + [1220227200000, 0.684], + [1220313600000, 0.689], + [1220400000000, 0.6926], + [1220486400000, 0.6903], + [1220572800000, 0.702], + [1220832000000, 0.7036], + [1220918400000, 0.7071], + [1221004800000, 0.7096], + [1221091200000, 0.7178], + [1221177600000, 0.711], + [1221436800000, 0.7068], + [1221523200000, 0.701], + [1221609600000, 0.7031], + [1221696000000, 0.6897], + [1221782400000, 0.7025], + [1222041600000, 0.6864], + [1222128000000, 0.6789], + [1222214400000, 0.6808], + [1222300800000, 0.6804], + [1222387200000, 0.6832], + [1222646400000, 0.697], + [1222732800000, 0.6993], + [1222819200000, 0.7103], + [1222905600000, 0.7194], + [1222992000000, 0.723], + [1223251200000, 0.7336], + [1223337600000, 0.7337], + [1223424000000, 0.7284], + [1223510400000, 0.731], + [1223596800000, 0.7365], + [1223856000000, 0.7333], + [1223942400000, 0.7273], + [1224028800000, 0.734], + [1224115200000, 0.7405], + [1224201600000, 0.7461], + [1224460800000, 0.745], + [1224547200000, 0.7586], + [1224633600000, 0.7787], + [1224720000000, 0.7807], + [1224806400000, 0.794], + [1225065600000, 0.8027], + [1225152000000, 0.7984], + [1225238400000, 0.7832], + [1225324800000, 0.7673], + [1225411200000, 0.784], + [1225670400000, 0.78], + [1225756800000, 0.7801], + [1225843200000, 0.7771], + [1225929600000, 0.7832], + [1226016000000, 0.784], + [1226275200000, 0.7758], + [1226361600000, 0.7846], + [1226448000000, 0.7982], + [1226534400000, 0.7985], + [1226620800000, 0.7891], + [1226880000000, 0.79], + [1226966400000, 0.7904], + [1227052800000, 0.7916], + [1227139200000, 0.7974], + [1227225600000, 0.7936], + [1227484800000, 0.783], + [1227571200000, 0.7807], + [1227657600000, 0.7732], + [1227744000000, 0.7753], + [1227830400000, 0.7858], + [1228089600000, 0.7932], + [1228176000000, 0.7877], + [1228262400000, 0.7923], + [1228348800000, 0.7925], + [1228435200000, 0.7897], + [1228694400000, 0.7781], + [1228780800000, 0.779], + [1228867200000, 0.7738], + [1228953600000, 0.7568], + [1229040000000, 0.7497], + [1229299200000, 0.7403], + [1229385600000, 0.7306], + [1229472000000, 0.7114], + [1229558400000, 0.6843], + [1229644800000, 0.7175], + [1229904000000, 0.7159], + [1229990400000, 0.7155], + [1230076800000, 0.7141], + [1230163200000, 0.7141], + [1230249600000, 0.7141], + [1230508800000, 0.7009], + [1230595200000, 0.7094], + [1230681600000, 0.7186], + [1230768000000, 0.7186], + [1230854400000, 0.7213], + [1231113600000, 0.7364], + [1231200000000, 0.7502], + [1231286400000, 0.7357], + [1231372800000, 0.7345], + [1231459200000, 0.7309], + [1231718400000, 0.7467], + [1231804800000, 0.7541], + [1231891200000, 0.7592], + [1231977600000, 0.7643], + [1232064000000, 0.7537], + [1232323200000, 0.7587], + [1232409600000, 0.7735], + [1232496000000, 0.7747], + [1232582400000, 0.7703], + [1232668800000, 0.7817], + [1232928000000, 0.7699], + [1233014400000, 0.7592], + [1233100800000, 0.7542], + [1233187200000, 0.7628], + [1233273600000, 0.7804], + [1233532800000, 0.7838], + [1233619200000, 0.7784], + [1233705600000, 0.7803], + [1233792000000, 0.7796], + [1233878400000, 0.7816], + [1234137600000, 0.7689], + [1234224000000, 0.7713], + [1234310400000, 0.773], + [1234396800000, 0.7793], + [1234483200000, 0.7799], + [1234742400000, 0.7835], + [1234828800000, 0.7916], + [1234915200000, 0.794], + [1235001600000, 0.7872], + [1235088000000, 0.7943], + [1235347200000, 0.7815], + [1235433600000, 0.7836], + [1235520000000, 0.7817], + [1235606400000, 0.7825], + [1235692800000, 0.791], + [1235952000000, 0.794], + [1236038400000, 0.7928], + [1236124800000, 0.7966], + [1236211200000, 0.7966], + [1236297600000, 0.7901], + [1236556800000, 0.796], + [1236643200000, 0.7824], + [1236729600000, 0.7822], + [1236816000000, 0.7825], + [1236902400000, 0.775], + [1237161600000, 0.7669], + [1237248000000, 0.7728], + [1237334400000, 0.7617], + [1237420800000, 0.7316], + [1237507200000, 0.7382], + [1237766400000, 0.7377], + [1237852800000, 0.7405], + [1237939200000, 0.7412], + [1238025600000, 0.735], + [1238112000000, 0.7523], + [1238371200000, 0.7581], + [1238457600000, 0.7515], + [1238544000000, 0.755], + [1238630400000, 0.7468], + [1238716800000, 0.745], + [1238976000000, 0.7411], + [1239062400000, 0.7545], + [1239148800000, 0.7559], + [1239235200000, 0.7535], + [1239321600000, 0.7535], + [1239580800000, 0.7535], + [1239667200000, 0.7533], + [1239753600000, 0.7592], + [1239840000000, 0.7579], + [1239926400000, 0.7659], + [1240185600000, 0.7713], + [1240272000000, 0.7734], + [1240358400000, 0.7725], + [1240444800000, 0.7664], + [1240531200000, 0.7558], + [1240790400000, 0.762], + [1240876800000, 0.7698], + [1240963200000, 0.7539], + [1241049600000, 0.7534], + [1241136000000, 0.7534], + [1241395200000, 0.7564], + [1241481600000, 0.7462], + [1241568000000, 0.7507], + [1241654400000, 0.7484], + [1241740800000, 0.745], + [1242000000000, 0.7368], + [1242086400000, 0.7309], + [1242172800000, 0.7342], + [1242259200000, 0.7374], + [1242345600000, 0.7399], + [1242604800000, 0.7412], + [1242691200000, 0.7347], + [1242777600000, 0.7306], + [1242864000000, 0.7263], + [1242950400000, 0.7158], + [1243209600000, 0.7139], + [1243296000000, 0.7191], + [1243382400000, 0.7195], + [1243468800000, 0.7218], + [1243555200000, 0.7094], + [1243814400000, 0.7033], + [1243900800000, 0.7024], + [1243987200000, 0.704], + [1244073600000, 0.7096], + [1244160000000, 0.7055], + [1244419200000, 0.7213], + [1244505600000, 0.7165], + [1244592000000, 0.7092], + [1244678400000, 0.716], + [1244764800000, 0.7142], + [1245024000000, 0.7221], + [1245110400000, 0.72], + [1245196800000, 0.7226], + [1245283200000, 0.7185], + [1245369600000, 0.7179], + [1245628800000, 0.7217], + [1245715200000, 0.7155], + [1245801600000, 0.7129], + [1245888000000, 0.7175], + [1245974400000, 0.7095], + [1246233600000, 0.7114], + [1246320000000, 0.7076], + [1246406400000, 0.7095], + [1246492800000, 0.7119], + [1246579200000, 0.7139], + [1246838400000, 0.7197], + [1246924800000, 0.7134], + [1247011200000, 0.7195], + [1247097600000, 0.7149], + [1247184000000, 0.7195], + [1247443200000, 0.7157], + [1247529600000, 0.7148], + [1247616000000, 0.7099], + [1247702400000, 0.7078], + [1247788800000, 0.7098], + [1248048000000, 0.7035], + [1248134400000, 0.7032], + [1248220800000, 0.7048], + [1248307200000, 0.7029], + [1248393600000, 0.703], + [1248652800000, 0.7009], + [1248739200000, 0.7029], + [1248825600000, 0.7091], + [1248912000000, 0.7117], + [1248998400000, 0.7074], + [1249257600000, 0.6993], + [1249344000000, 0.6953], + [1249430400000, 0.6941], + [1249516800000, 0.696], + [1249603200000, 0.6966], + [1249862400000, 0.7042], + [1249948800000, 0.706], + [1250035200000, 0.7058], + [1250121600000, 0.6997], + [1250208000000, 0.6997], + [1250467200000, 0.7107], + [1250553600000, 0.7093], + [1250640000000, 0.7087], + [1250726400000, 0.7022], + [1250812800000, 0.6979], + [1251072000000, 0.6983], + [1251158400000, 0.6982], + [1251244800000, 0.7009], + [1251331200000, 0.701], + [1251417600000, 0.6963], + [1251676800000, 0.7008], + [1251763200000, 0.6987], + [1251849600000, 0.7033], + [1251936000000, 0.6977], + [1252022400000, 0.7013], + [1252281600000, 0.6979], + [1252368000000, 0.691], + [1252454400000, 0.6887], + [1252540800000, 0.6876], + [1252627200000, 0.6853], + [1252886400000, 0.6869], + [1252972800000, 0.6845], + [1253059200000, 0.6817], + [1253145600000, 0.6798], + [1253232000000, 0.6801], + [1253491200000, 0.6823], + [1253577600000, 0.6767], + [1253664000000, 0.6766], + [1253750400000, 0.6772], + [1253836800000, 0.6818], + [1254096000000, 0.6827], + [1254182400000, 0.6874], + [1254268800000, 0.683], + [1254355200000, 0.6879], + [1254441600000, 0.688], + [1254700800000, 0.6843], + [1254787200000, 0.6794], + [1254873600000, 0.6806], + [1254960000000, 0.6775], + [1255046400000, 0.6781], + [1255305600000, 0.6774], + [1255392000000, 0.6729], + [1255478400000, 0.6721], + [1255564800000, 0.6729], + [1255651200000, 0.6726], + [1255910400000, 0.6704], + [1255996800000, 0.6681], + [1256083200000, 0.6703], + [1256169600000, 0.6668], + [1256256000000, 0.6659], + [1256515200000, 0.6659], + [1256601600000, 0.6724], + [1256688000000, 0.6765], + [1256774400000, 0.6763], + [1256860800000, 0.6758], + [1257120000000, 0.6771], + [1257206400000, 0.6823], + [1257292800000, 0.6776], + [1257379200000, 0.6727], + [1257465600000, 0.673], + [1257724800000, 0.6675], + [1257811200000, 0.6683], + [1257897600000, 0.6651], + [1257984000000, 0.6703], + [1258070400000, 0.6727], + [1258329600000, 0.6683], + [1258416000000, 0.6724], + [1258502400000, 0.6687], + [1258588800000, 0.6729], + [1258675200000, 0.6751], + [1258934400000, 0.6682], + [1259020800000, 0.6681], + [1259107200000, 0.6631], + [1259193600000, 0.6636], + [1259280000000, 0.6704], + [1259539200000, 0.6657], + [1259625600000, 0.6635], + [1259712000000, 0.6628], + [1259798400000, 0.6615], + [1259884800000, 0.6638], + [1260144000000, 0.6764], + [1260230400000, 0.677], + [1260316800000, 0.6772], + [1260403200000, 0.679], + [1260489600000, 0.6777], + [1260748800000, 0.6828], + [1260835200000, 0.6878], + [1260921600000, 0.6869], + [1261008000000, 0.6973], + [1261094400000, 0.6976], + [1261353600000, 0.6961], + [1261440000000, 0.7004], + [1261526400000, 0.7006], + [1261612800000, 0.6946], + [1261699200000, 0.6946], + [1261958400000, 0.6943], + [1262044800000, 0.693], + [1262131200000, 0.6975], + [1262217600000, 0.6943], + [1262304000000, 0.6943], + [1262563200000, 0.6951], + [1262649600000, 0.6925], + [1262736000000, 0.697], + [1262822400000, 0.6992], + [1262908800000, 0.7007], + [1263168000000, 0.6884], + [1263254400000, 0.6907], + [1263340800000, 0.6868], + [1263427200000, 0.6904], + [1263513600000, 0.6958], + [1263772800000, 0.696], + [1263859200000, 0.7004], + [1263945600000, 0.7077], + [1264032000000, 0.7111], + [1264118400000, 0.7076], + [1264377600000, 0.7068], + [1264464000000, 0.7101], + [1264550400000, 0.7107], + [1264636800000, 0.7144], + [1264723200000, 0.7161], + [1264982400000, 0.7189], + [1265068800000, 0.7176], + [1265155200000, 0.7152], + [1265241600000, 0.7223], + [1265328000000, 0.7305], + [1265587200000, 0.7314], + [1265673600000, 0.7268], + [1265760000000, 0.7279], + [1265846400000, 0.7291], + [1265932800000, 0.7369], + [1266192000000, 0.735], + [1266278400000, 0.7328], + [1266364800000, 0.7286], + [1266451200000, 0.7372], + [1266537600000, 0.7398], + [1266796800000, 0.734], + [1266883200000, 0.7366], + [1266969600000, 0.7383], + [1267056000000, 0.7414], + [1267142400000, 0.737], + [1267401600000, 0.7395], + [1267488000000, 0.7382], + [1267574400000, 0.7332], + [1267660800000, 0.7317], + [1267747200000, 0.7364], + [1268006400000, 0.7321], + [1268092800000, 0.7377], + [1268179200000, 0.7349], + [1268265600000, 0.7323], + [1268352000000, 0.7266], + [1268611200000, 0.7298], + [1268697600000, 0.7288], + [1268784000000, 0.7271], + [1268870400000, 0.7322], + [1268956800000, 0.7382], + [1269216000000, 0.7424], + [1269302400000, 0.7398], + [1269388800000, 0.7498], + [1269475200000, 0.7488], + [1269561600000, 0.749], + [1269820800000, 0.7424], + [1269907200000, 0.7418], + [1269993600000, 0.742], + [1270080000000, 0.7426], + [1270166400000, 0.7426], + [1270425600000, 0.7426], + [1270512000000, 0.7466], + [1270598400000, 0.7497], + [1270684800000, 0.7522], + [1270771200000, 0.7473], + [1271030400000, 0.7362], + [1271116800000, 0.7363], + [1271203200000, 0.7346], + [1271289600000, 0.7384], + [1271376000000, 0.7389], + [1271635200000, 0.7446], + [1271721600000, 0.7416], + [1271808000000, 0.7479], + [1271894400000, 0.7498], + [1271980800000, 0.7514], + [1272240000000, 0.7508], + [1272326400000, 0.7525], + [1272412800000, 0.7551], + [1272499200000, 0.7545], + [1272585600000, 0.7511], + [1272844800000, 0.7555], + [1272931200000, 0.7641], + [1273017600000, 0.7739], + [1273104000000, 0.7858], + [1273190400000, 0.7847], + [1273449600000, 0.7712], + [1273536000000, 0.7876], + [1273622400000, 0.7884], + [1273708800000, 0.7946], + [1273795200000, 0.8006], + [1274054400000, 0.8099], + [1274140800000, 0.8047], + [1274227200000, 0.8151], + [1274313600000, 0.8109], + [1274400000000, 0.8003], + [1274659200000, 0.8092], + [1274745600000, 0.8182], + [1274832000000, 0.8125], + [1274918400000, 0.8161], + [1275004800000, 0.8076], + [1275264000000, 0.8126], + [1275350400000, 0.8228], + [1275436800000, 0.8186], + [1275523200000, 0.8152], + [1275609600000, 0.8293], + [1275868800000, 0.8363], + [1275955200000, 0.8375], + [1276041600000, 0.8327], + [1276128000000, 0.8303], + [1276214400000, 0.8247], + [1276473600000, 0.8165], + [1276560000000, 0.8159], + [1276646400000, 0.8146], + [1276732800000, 0.809], + [1276819200000, 0.8084], + [1277078400000, 0.8071], + [1277164800000, 0.8159], + [1277251200000, 0.815], + [1277337600000, 0.8156], + [1277424000000, 0.8135], + [1277683200000, 0.8105], + [1277769600000, 0.8199], + [1277856000000, 0.815], + [1277942400000, 0.8113], + [1278028800000, 0.797], + [1278288000000, 0.7981], + [1278374400000, 0.7951], + [1278460800000, 0.7958], + [1278547200000, 0.79], + [1278633600000, 0.7914], + [1278892800000, 0.7955], + [1278979200000, 0.7957], + [1279065600000, 0.7873], + [1279152000000, 0.7796], + [1279238400000, 0.7693], + [1279497600000, 0.7719], + [1279584000000, 0.7787], + [1279670400000, 0.7803], + [1279756800000, 0.7783], + [1279843200000, 0.7755], + [1280102400000, 0.7734], + [1280188800000, 0.7674], + [1280275200000, 0.7698], + [1280361600000, 0.7653], + [1280448000000, 0.7677], + [1280707200000, 0.765], + [1280793600000, 0.7565], + [1280880000000, 0.7573], + [1280966400000, 0.7586], + [1281052800000, 0.7591], + [1281312000000, 0.7546], + [1281398400000, 0.7615], + [1281484800000, 0.7684], + [1281571200000, 0.782], + [1281657600000, 0.7814], + [1281916800000, 0.7801], + [1282003200000, 0.7777], + [1282089600000, 0.7765], + [1282176000000, 0.7792], + [1282262400000, 0.7868], + [1282521600000, 0.7873], + [1282608000000, 0.7931], + [1282694400000, 0.7929], + [1282780800000, 0.7879], + [1282867200000, 0.7867], + [1283126400000, 0.7875], + [1283212800000, 0.7887], + [1283299200000, 0.7814], + [1283385600000, 0.7803], + [1283472000000, 0.7793], + [1283731200000, 0.7769], + [1283817600000, 0.7848], + [1283904000000, 0.7877], + [1283990400000, 0.7866], + [1284076800000, 0.786], + [1284336000000, 0.7813], + [1284422400000, 0.7783], + [1284508800000, 0.77], + [1284595200000, 0.7647], + [1284681600000, 0.7658], + [1284940800000, 0.765], + [1285027200000, 0.7623], + [1285113600000, 0.7484], + [1285200000000, 0.7507], + [1285286400000, 0.7457], + [1285545600000, 0.7421], + [1285632000000, 0.743], + [1285718400000, 0.7348], + [1285804800000, 0.7328], + [1285891200000, 0.7286], + [1286150400000, 0.7298], + [1286236800000, 0.7258], + [1286323200000, 0.7218], + [1286409600000, 0.7159], + [1286496000000, 0.7209], + [1286755200000, 0.7177], + [1286841600000, 0.723], + [1286928000000, 0.7165], + [1287014400000, 0.7093], + [1287100800000, 0.7099], + [1287360000000, 0.7197], + [1287446400000, 0.7217], + [1287532800000, 0.7215], + [1287619200000, 0.7136], + [1287705600000, 0.7178], + [1287964800000, 0.7128], + [1288051200000, 0.7189], + [1288137600000, 0.7246], + [1288224000000, 0.7218], + [1288310400000, 0.7218], + [1288569600000, 0.7182], + [1288656000000, 0.7135], + [1288742400000, 0.7137], + [1288828800000, 0.7021], + [1288915200000, 0.7101], + [1289174400000, 0.7186], + [1289260800000, 0.7172], + [1289347200000, 0.7263], + [1289433600000, 0.73], + [1289520000000, 0.7294], + [1289779200000, 0.734], + [1289865600000, 0.7347], + [1289952000000, 0.7419], + [1290038400000, 0.7329], + [1290124800000, 0.7314], + [1290384000000, 0.7329], + [1290470400000, 0.7411], + [1290556800000, 0.7498], + [1290643200000, 0.7508], + [1290729600000, 0.7562], + [1290988800000, 0.7608], + [1291075200000, 0.7694], + [1291161600000, 0.7626], + [1291248000000, 0.7603], + [1291334400000, 0.755], + [1291593600000, 0.7531], + [1291680000000, 0.7484], + [1291766400000, 0.7577], + [1291852800000, 0.7569], + [1291939200000, 0.7552], + [1292198400000, 0.7538], + [1292284800000, 0.7444], + [1292371200000, 0.7486], + [1292457600000, 0.7555], + [1292544000000, 0.7542], + [1292803200000, 0.7607], + [1292889600000, 0.7603], + [1292976000000, 0.7628], + [1293062400000, 0.7656], + [1293148800000, 0.7635], + [1293408000000, 0.7614], + [1293494400000, 0.758], + [1293580800000, 0.7614], + [1293667200000, 0.7531], + [1293753600000, 0.7485], + [1294012800000, 0.7493], + [1294099200000, 0.7452], + [1294185600000, 0.7569], + [1294272000000, 0.764], + [1294358400000, 0.7716], + [1294617600000, 0.7751], + [1294704000000, 0.7724], + [1294790400000, 0.7709], + [1294876800000, 0.7577], + [1294963200000, 0.7492], + [1295222400000, 0.7514], + [1295308800000, 0.748], + [1295395200000, 0.7405], + [1295481600000, 0.7424], + [1295568000000, 0.7397], + [1295827200000, 0.737], + [1295913600000, 0.7356], + [1296000000000, 0.731], + [1296086400000, 0.7292], + [1296172800000, 0.7295], + [1296432000000, 0.7305], + [1296518400000, 0.7271], + [1296604800000, 0.7246], + [1296691200000, 0.7276], + [1296777600000, 0.7337], + [1297036800000, 0.7379], + [1297123200000, 0.7335], + [1297209600000, 0.7329], + [1297296000000, 0.7352], + [1297382400000, 0.7395], + [1297641600000, 0.7441], + [1297728000000, 0.7403], + [1297814400000, 0.7403], + [1297900800000, 0.7376], + [1297987200000, 0.7339], + [1298246400000, 0.7317], + [1298332800000, 0.7318], + [1298419200000, 0.7284], + [1298505600000, 0.7262], + [1298592000000, 0.7267], + [1298851200000, 0.723], + [1298937600000, 0.7234], + [1299024000000, 0.7243], + [1299110400000, 0.7221], + [1299196800000, 0.7166], + [1299456000000, 0.713], + [1299542400000, 0.7196], + [1299628800000, 0.7181], + [1299715200000, 0.7238], + [1299801600000, 0.7262], + [1300060800000, 0.717], + [1300147200000, 0.7204], + [1300233600000, 0.7169], + [1300320000000, 0.7142], + [1300406400000, 0.7078], + [1300665600000, 0.7046], + [1300752000000, 0.7038], + [1300838400000, 0.7075], + [1300924800000, 0.7079], + [1301011200000, 0.7086], + [1301270400000, 0.7128], + [1301356800000, 0.711], + [1301443200000, 0.7098], + [1301529600000, 0.704], + [1301616000000, 0.7073], + [1301875200000, 0.7023], + [1301961600000, 0.706], + [1302048000000, 0.6994], + [1302134400000, 0.7002], + [1302220800000, 0.6945], + [1302480000000, 0.6929], + [1302566400000, 0.6912], + [1302652800000, 0.6901], + [1302739200000, 0.6945], + [1302825600000, 0.6921], + [1303084800000, 0.7006], + [1303171200000, 0.6993], + [1303257600000, 0.689], + [1303344000000, 0.6858], + [1303430400000, 0.6858], + [1303689600000, 0.6858], + [1303776000000, 0.6842], + [1303862400000, 0.6819], + [1303948800000, 0.676], + [1304035200000, 0.673], + [1304294400000, 0.6741], + [1304380800000, 0.6767], + [1304467200000, 0.6721], + [1304553600000, 0.6751], + [1304640000000, 0.6897], + [1304899200000, 0.6947], + [1304985600000, 0.6966], + [1305072000000, 0.6966], + [1305158400000, 0.7067], + [1305244800000, 0.7004], + [1305504000000, 0.7072], + [1305590400000, 0.7058], + [1305676800000, 0.703], + [1305763200000, 0.7011], + [1305849600000, 0.7025], + [1306108800000, 0.7134], + [1306195200000, 0.7099], + [1306281600000, 0.7109], + [1306368000000, 0.7059], + [1306454400000, 0.7011], + [1306713600000, 0.7008], + [1306800000000, 0.6953], + [1306886400000, 0.6942], + [1306972800000, 0.6917], + [1307059200000, 0.6903], + [1307318400000, 0.6852], + [1307404800000, 0.6826], + [1307491200000, 0.6847], + [1307577600000, 0.6844], + [1307664000000, 0.6904], + [1307923200000, 0.6968], + [1308009600000, 0.6922], + [1308096000000, 0.6998], + [1308182400000, 0.7099], + [1308268800000, 0.7009], + [1308528000000, 0.7026], + [1308614400000, 0.6958], + [1308700800000, 0.6947], + [1308787200000, 0.7037], + [1308873600000, 0.7033], + [1309132800000, 0.7041], + [1309219200000, 0.7013], + [1309305600000, 0.6933], + [1309392000000, 0.692], + [1309478400000, 0.6903], + [1309737600000, 0.6898], + [1309824000000, 0.6916], + [1309910400000, 0.6985], + [1309996800000, 0.702], + [1310083200000, 0.7022], + [1310342400000, 0.7115], + [1310428800000, 0.7157], + [1310515200000, 0.7107], + [1310601600000, 0.7042], + [1310688000000, 0.707], + [1310947200000, 0.7121], + [1311033600000, 0.7063], + [1311120000000, 0.704], + [1311206400000, 0.7032], + [1311292800000, 0.695], + [1311552000000, 0.6955], + [1311638400000, 0.6911], + [1311724800000, 0.6923], + [1311811200000, 0.7014], + [1311897600000, 0.7014], + [1312156800000, 0.6938], + [1312243200000, 0.7058], + [1312329600000, 0.6994], + [1312416000000, 0.7029], + [1312502400000, 0.7066], + [1312761600000, 0.7031], + [1312848000000, 0.701], + [1312934400000, 0.6961], + [1313020800000, 0.7072], + [1313107200000, 0.7019], + [1313366400000, 0.699], + [1313452800000, 0.6965], + [1313539200000, 0.6909], + [1313625600000, 0.696], + [1313712000000, 0.6953], + [1313971200000, 0.6939], + [1314057600000, 0.6916], + [1314144000000, 0.693], + [1314230400000, 0.6934], + [1314316800000, 0.6944], + [1314576000000, 0.6904], + [1314662400000, 0.6944], + [1314748800000, 0.6921], + [1314835200000, 0.7001], + [1314921600000, 0.7016], + [1315180800000, 0.708], + [1315267200000, 0.7094], + [1315353600000, 0.7126], + [1315440000000, 0.7121], + [1315526400000, 0.7238], + [1315785600000, 0.7324], + [1315872000000, 0.733], + [1315958400000, 0.7285], + [1316044800000, 0.725], + [1316131200000, 0.7268], + [1316390400000, 0.7332], + [1316476800000, 0.7295], + [1316563200000, 0.7335], + [1316649600000, 0.7437], + [1316736000000, 0.7447], + [1316995200000, 0.7408], + [1317081600000, 0.7365], + [1317168000000, 0.7337], + [1317254400000, 0.7346], + [1317340800000, 0.7407], + [1317600000000, 0.7505], + [1317686400000, 0.7588], + [1317772800000, 0.7499], + [1317859200000, 0.7537], + [1317945600000, 0.7445], + [1318204800000, 0.7358], + [1318291200000, 0.735], + [1318377600000, 0.7265], + [1318464000000, 0.7286], + [1318550400000, 0.7244], + [1318809600000, 0.726], + [1318896000000, 0.7313], + [1318982400000, 0.7233], + [1319068800000, 0.7244], + [1319155200000, 0.7248], + [1319414400000, 0.7218], + [1319500800000, 0.7186], + [1319587200000, 0.7181], + [1319673600000, 0.7125], + [1319760000000, 0.7063], + [1320019200000, 0.7143], + [1320105600000, 0.7339], + [1320192000000, 0.7243], + [1320278400000, 0.7262], + [1320364800000, 0.7262], + [1320624000000, 0.7278], + [1320710400000, 0.7254], + [1320796800000, 0.7336], + [1320883200000, 0.7345], + [1320969600000, 0.7327], + [1321228800000, 0.7322], + [1321315200000, 0.7391], + [1321401600000, 0.7417], + [1321488000000, 0.7419], + [1321574400000, 0.7367], + [1321833600000, 0.7432], + [1321920000000, 0.7389], + [1322006400000, 0.7471], + [1322092800000, 0.7479], + [1322179200000, 0.756], + [1322438400000, 0.7493], + [1322524800000, 0.75], + [1322611200000, 0.7454], + [1322697600000, 0.7413], + [1322784000000, 0.7402], + [1323043200000, 0.744], + [1323129600000, 0.7467], + [1323216000000, 0.7477], + [1323302400000, 0.7458], + [1323388800000, 0.7473], + [1323648000000, 0.7548], + [1323734400000, 0.7588], + [1323820800000, 0.7697], + [1323907200000, 0.7682], + [1323993600000, 0.7656], + [1324252800000, 0.767], + [1324339200000, 0.765], + [1324425600000, 0.7661], + [1324512000000, 0.7666], + [1324598400000, 0.766], + [1324857600000, 0.766], + [1324944000000, 0.7653], + [1325030400000, 0.765], + [1325116800000, 0.776], + [1325203200000, 0.773], + [1325462400000, 0.7732], + [1325548800000, 0.7685], + [1325635200000, 0.7724], + [1325721600000, 0.7794], + [1325808000000, 0.7828], + [1326067200000, 0.7858], + [1326153600000, 0.7809], + [1326240000000, 0.7864], + [1326326400000, 0.7853], + [1326412800000, 0.7831], + [1326672000000, 0.7894], + [1326758400000, 0.782], + [1326844800000, 0.7795], + [1326931200000, 0.7746], + [1327017600000, 0.7752], + [1327276800000, 0.7683], + [1327363200000, 0.7692], + [1327449600000, 0.7728], + [1327536000000, 0.7608], + [1327622400000, 0.7608], + [1327881600000, 0.7629], + [1327968000000, 0.7591], + [1328054400000, 0.7591], + [1328140800000, 0.7638], + [1328227200000, 0.76], + [1328486400000, 0.7669], + [1328572800000, 0.7627], + [1328659200000, 0.7535], + [1328745600000, 0.7527], + [1328832000000, 0.7583], + [1329091200000, 0.7546], + [1329177600000, 0.7595], + [1329264000000, 0.7639], + [1329350400000, 0.7704], + [1329436800000, 0.76], + [1329696000000, 0.7539], + [1329782400000, 0.7564], + [1329868800000, 0.756], + [1329955200000, 0.752], + [1330041600000, 0.7457], + [1330300800000, 0.747], + [1330387200000, 0.7434], + [1330473600000, 0.744], + [1330560000000, 0.7513], + [1330646400000, 0.7567], + [1330905600000, 0.7565], + [1330992000000, 0.7604], + [1331078400000, 0.7623], + [1331164800000, 0.7553], + [1331251200000, 0.7582], + [1331510400000, 0.7624], + [1331596800000, 0.766], + [1331683200000, 0.7657], + [1331769600000, 0.766], + [1331856000000, 0.7625], + [1332115200000, 0.7606], + [1332201600000, 0.7578], + [1332288000000, 0.7562], + [1332374400000, 0.7596], + [1332460800000, 0.7553], + [1332720000000, 0.7533], + [1332806400000, 0.7501], + [1332892800000, 0.7499], + [1332979200000, 0.7536], + [1333065600000, 0.7488], + [1333324800000, 0.7509], + [1333411200000, 0.7511], + [1333497600000, 0.761], + [1333584000000, 0.7653], + [1333670400000, 0.7653], + [1333929600000, 0.7653], + [1334016000000, 0.7626], + [1334102400000, 0.7617], + [1334188800000, 0.7604], + [1334275200000, 0.7607], + [1334534400000, 0.7679], + [1334620800000, 0.7616], + [1334707200000, 0.7639], + [1334793600000, 0.7643], + [1334880000000, 0.7581], + [1335139200000, 0.7617], + [1335225600000, 0.7599], + [1335312000000, 0.7573], + [1335398400000, 0.7568], + [1335484800000, 0.756], + [1335744000000, 0.7569], + [1335830400000, 0.7569], + [1335916800000, 0.7617], + [1336003200000, 0.7621], + [1336089600000, 0.7616], + [1336348800000, 0.7674], + [1336435200000, 0.7679], + [1336521600000, 0.7723], + [1336608000000, 0.7716], + [1336694400000, 0.7727], + [1336953600000, 0.7775], + [1337040000000, 0.7787], + [1337126400000, 0.7852], + [1337212800000, 0.7886], + [1337299200000, 0.7862], + [1337558400000, 0.7844], + [1337644800000, 0.7833], + [1337731200000, 0.7901], + [1337817600000, 0.7965], + [1337904000000, 0.7972], + [1338163200000, 0.7959], + [1338249600000, 0.7986], + [1338336000000, 0.8041], + [1338422400000, 0.8064], + [1338508800000, 0.8117], + [1338768000000, 0.8042], + [1338854400000, 0.8047], + [1338940800000, 0.8011], + [1339027200000, 0.7941], + [1339113600000, 0.8022], + [1339372800000, 0.7973], + [1339459200000, 0.8006], + [1339545600000, 0.7979], + [1339632000000, 0.7968], + [1339718400000, 0.794], + [1339977600000, 0.7926], + [1340064000000, 0.7926], + [1340150400000, 0.7873], + [1340236800000, 0.7894], + [1340323200000, 0.7976], + [1340582400000, 0.8009], + [1340668800000, 0.8017], + [1340755200000, 0.8015], + [1340841600000, 0.8054], + [1340928000000, 0.7944], + [1341187200000, 0.7942], + [1341273600000, 0.7953], + [1341360000000, 0.7963], + [1341446400000, 0.8049], + [1341532800000, 0.8081], + [1341792000000, 0.8136], + [1341878400000, 0.8141], + [1341964800000, 0.8158], + [1342051200000, 0.8213], + [1342137600000, 0.8208], + [1342396800000, 0.8213], + [1342483200000, 0.8144], + [1342569600000, 0.8175], + [1342656000000, 0.814], + [1342742400000, 0.8198], + [1343001600000, 0.8262], + [1343088000000, 0.8273], + [1343174400000, 0.8242], + [1343260800000, 0.8158], + [1343347200000, 0.812], + [1343606400000, 0.8167], + [1343692800000, 0.8142], + [1343779200000, 0.8132], + [1343865600000, 0.8101], + [1343952000000, 0.8168], + [1344211200000, 0.8079], + [1344297600000, 0.8042], + [1344384000000, 0.8107], + [1344470400000, 0.813], + [1344556800000, 0.8156], + [1344816000000, 0.8105], + [1344902400000, 0.8097], + [1344988800000, 0.8147], + [1345075200000, 0.8145], + [1345161600000, 0.8107], + [1345420800000, 0.8131], + [1345507200000, 0.8047], + [1345593600000, 0.8034], + [1345680000000, 0.7968], + [1345766400000, 0.7997], + [1346025600000, 0.7982], + [1346112000000, 0.797], + [1346198400000, 0.7972], + [1346284800000, 0.7973], + [1346371200000, 0.7931], + [1346630400000, 0.7958], + [1346716800000, 0.7951], + [1346803200000, 0.7951], + [1346889600000, 0.7914], + [1346976000000, 0.7871], + [1347235200000, 0.7828], + [1347321600000, 0.7821], + [1347408000000, 0.7755], + [1347494400000, 0.7747], + [1347580800000, 0.7638], + [1347840000000, 0.7643], + [1347926400000, 0.7661], + [1348012800000, 0.7692], + [1348099200000, 0.7721], + [1348185600000, 0.77], + [1348444800000, 0.7743], + [1348531200000, 0.7734], + [1348617600000, 0.7786], + [1348704000000, 0.7769], + [1348790400000, 0.7735], + [1349049600000, 0.7767], + [1349136000000, 0.7735], + [1349222400000, 0.7751], + [1349308800000, 0.7722], + [1349395200000, 0.7692], + [1349654400000, 0.7718], + [1349740800000, 0.7721], + [1349827200000, 0.776], + [1349913600000, 0.7742], + [1350000000000, 0.7711], + [1350259200000, 0.7711], + [1350345600000, 0.7666], + [1350432000000, 0.7623], + [1350518400000, 0.7624], + [1350604800000, 0.7673], + [1350864000000, 0.7656], + [1350950400000, 0.769], + [1351036800000, 0.7728], + [1351123200000, 0.7697], + [1351209600000, 0.7748], + [1351468800000, 0.7754], + [1351555200000, 0.7716], + [1351641600000, 0.7697], + [1351728000000, 0.7708], + [1351814400000, 0.7783], + [1352073600000, 0.7828], + [1352160000000, 0.7814], + [1352246400000, 0.7847], + [1352332800000, 0.7853], + [1352419200000, 0.7879], + [1352678400000, 0.7853], + [1352764800000, 0.7877], + [1352851200000, 0.7859], + [1352937600000, 0.784], + [1353024000000, 0.7847], + [1353283200000, 0.7837], + [1353369600000, 0.7808], + [1353456000000, 0.781], + [1353542400000, 0.7757], + [1353628800000, 0.7748], + [1353888000000, 0.7715], + [1353974400000, 0.7716], + [1354060800000, 0.7758], + [1354147200000, 0.7697], + [1354233600000, 0.7702], + [1354492800000, 0.766], + [1354579200000, 0.7639], + [1354665600000, 0.7655], + [1354752000000, 0.7651], + [1354838400000, 0.775], + [1355097600000, 0.7735], + [1355184000000, 0.7697], + [1355270400000, 0.767], + [1355356800000, 0.7648], + [1355443200000, 0.7646], + [1355702400000, 0.76], + [1355788800000, 0.7589], + [1355875200000, 0.7519], + [1355961600000, 0.755], + [1356048000000, 0.7572], + [1356307200000, 0.7566], + [1356566400000, 0.7539], + [1356652800000, 0.7587], + [1356912000000, 0.758], + [1357084800000, 0.7541], + [1357171200000, 0.7633], + [1357257600000, 0.7686], + [1357516800000, 0.767], + [1357603200000, 0.7643], + [1357689600000, 0.766], + [1357776000000, 0.7627], + [1357862400000, 0.7535], + [1358121600000, 0.7497], + [1358208000000, 0.7505], + [1358294400000, 0.7533], + [1358380800000, 0.7482], + [1358467200000, 0.7506], + [1358726400000, 0.7507], + [1358812800000, 0.751], + [1358899200000, 0.7503], + [1358985600000, 0.7492], + [1359072000000, 0.7425], + [1359331200000, 0.7439], + [1359417600000, 0.7445], + [1359504000000, 0.7386], + [1359590400000, 0.7381], + [1359676800000, 0.733], + [1359936000000, 0.738], + [1360022400000, 0.7388], + [1360108800000, 0.7399], + [1360195200000, 0.7383], + [1360281600000, 0.7478], + [1360540800000, 0.7469], + [1360627200000, 0.7443], + [1360713600000, 0.7419], + [1360800000000, 0.7505], + [1360886400000, 0.7506], + [1361145600000, 0.7491], + [1361232000000, 0.7492], + [1361318400000, 0.748], + [1361404800000, 0.7585], + [1361491200000, 0.7585], + [1361750400000, 0.7518], + [1361836800000, 0.7648], + [1361923200000, 0.7636], + [1362009600000, 0.7618], + [1362096000000, 0.7693], + [1362355200000, 0.7689], + [1362441600000, 0.7673], + [1362528000000, 0.7673], + [1362614400000, 0.7687], + [1362700800000, 0.764], + [1362960000000, 0.7697], + [1363046400000, 0.7662], + [1363132800000, 0.7705], + [1363219200000, 0.7731], + [1363305600000, 0.7643], + [1363564800000, 0.7736], + [1363651200000, 0.7727], + [1363737600000, 0.7726], + [1363824000000, 0.7747], + [1363910400000, 0.7724], + [1364169600000, 0.7732], + [1364256000000, 0.7776], + [1364342400000, 0.7833], + [1364428800000, 0.781], + [1364860800000, 0.7789], + [1364947200000, 0.7796], + [1365033600000, 0.7803], + [1365120000000, 0.7727], + [1365379200000, 0.768], + [1365465600000, 0.767], + [1365552000000, 0.7643], + [1365638400000, 0.7624], + [1365724800000, 0.7663], + [1365984000000, 0.7646], + [1366070400000, 0.7618], + [1366156800000, 0.7618], + [1366243200000, 0.7667], + [1366329600000, 0.7626], + [1366588800000, 0.7671], + [1366675200000, 0.7699], + [1366761600000, 0.769], + [1366848000000, 0.7646], + [1366934400000, 0.7694], + [1367193600000, 0.7627], + [1367280000000, 0.7651], + [1367452800000, 0.7582], + [1367539200000, 0.7626], + [1367798400000, 0.7631], + [1367884800000, 0.7631], + [1367971200000, 0.7614], + [1368057600000, 0.761], + [1368144000000, 0.77], + [1368403200000, 0.7709], + [1368489600000, 0.7707], + [1368576000000, 0.7775], + [1368662400000, 0.7759], + [1368748800000, 0.7772], + [1369008000000, 0.7781], + [1369094400000, 0.7773], + [1369180800000, 0.7739], + [1369267200000, 0.776], + [1369353600000, 0.773], + [1369612800000, 0.773], + [1369699200000, 0.773], + [1369785600000, 0.7722], + [1369872000000, 0.7727], + [1369958400000, 0.769], + [1370217600000, 0.7689], + [1370304000000, 0.7639], + [1370390400000, 0.7654], + [1370476800000, 0.7624], + [1370563200000, 0.7542], + [1370822400000, 0.7572], + [1370908800000, 0.7535], + [1370995200000, 0.7533], + [1371081600000, 0.7511], + [1371168000000, 0.7518], + [1371427200000, 0.7499], + [1371513600000, 0.7478], + [1371600000000, 0.746], + [1371686400000, 0.7577], + [1371772800000, 0.7588], + [1372032000000, 0.7643], + [1372118400000, 0.7615], + [1372204800000, 0.7679], + [1372291200000, 0.7674], + [1372377600000, 0.7646], + [1372636800000, 0.7671], + [1372723200000, 0.7683], + [1372809600000, 0.7718], + [1372896000000, 0.7703], + [1372982400000, 0.7763], + [1373241600000, 0.7783], + [1373328000000, 0.7779], + [1373414400000, 0.7806], + [1373500800000, 0.7667], + [1373587200000, 0.7673], + [1373846400000, 0.7686], + [1373932800000, 0.7624], + [1374019200000, 0.7614], + [1374105600000, 0.7639], + [1374192000000, 0.7621], + [1374451200000, 0.7596], + [1374537600000, 0.7588], + [1374624000000, 0.755], + [1374710400000, 0.7576], + [1374796800000, 0.7542], + [1375056000000, 0.7537], + [1375142400000, 0.7529], + [1375228800000, 0.7534], + [1375315200000, 0.7556], + [1375401600000, 0.7575], + [1375660800000, 0.7544], + [1375747200000, 0.7531], + [1375833600000, 0.7517], + [1375920000000, 0.7486], + [1376006400000, 0.7479], + [1376265600000, 0.7531], + [1376352000000, 0.7525], + [1376438400000, 0.7552], + [1376524800000, 0.7521], + [1376611200000, 0.7497], + [1376870400000, 0.7495], + [1376956800000, 0.7468], + [1377043200000, 0.7473], + [1377129600000, 0.7507], + [1377216000000, 0.7489], + [1377475200000, 0.7485], + [1377561600000, 0.7498], + [1377648000000, 0.7493], + [1377734400000, 0.7539], + [1377820800000, 0.7557], + [1378080000000, 0.7573], + [1378166400000, 0.7593], + [1378252800000, 0.7593], + [1378339200000, 0.7576], + [1378425600000, 0.7625], + [1378684800000, 0.758], + [1378771200000, 0.7554], + [1378857600000, 0.7538], + [1378944000000, 0.7525], + [1379030400000, 0.7523], + [1379289600000, 0.7488], + [1379376000000, 0.7488], + [1379462400000, 0.7491], + [1379548800000, 0.7384], + [1379635200000, 0.7401], + [1379894400000, 0.7404], + [1379980800000, 0.7423], + [1380067200000, 0.7406], + [1380153600000, 0.7409], + [1380240000000, 0.7388], + [1380499200000, 0.7406], + [1380585600000, 0.7379], + [1380672000000, 0.74], + [1380758400000, 0.7357], + [1380844800000, 0.7358], + [1381104000000, 0.7369], + [1381190400000, 0.7367], + [1381276800000, 0.74], + [1381363200000, 0.7391], + [1381449600000, 0.7372], + [1381708800000, 0.7373], + [1381795200000, 0.7412], + [1381881600000, 0.7375], + [1381968000000, 0.7321], + [1382054400000, 0.7309], + [1382313600000, 0.7318], + [1382400000000, 0.7314], + [1382486400000, 0.7273], + [1382572800000, 0.7245], + [1382659200000, 0.7259], + [1382918400000, 0.7256], + [1383004800000, 0.7264], + [1383091200000, 0.7271], + [1383177600000, 0.7332], + [1383264000000, 0.7406], + [1383523200000, 0.7405], + [1383609600000, 0.7412], + [1383696000000, 0.7399], + [1383782400000, 0.7483], + [1383868800000, 0.7446], + [1384128000000, 0.7467], + [1384214400000, 0.7446], + [1384300800000, 0.7455], + [1384387200000, 0.7444], + [1384473600000, 0.743], + [1384732800000, 0.7399], + [1384819200000, 0.7407], + [1384905600000, 0.7394], + [1384992000000, 0.7424], + [1385078400000, 0.7399], + [1385337600000, 0.7401], + [1385424000000, 0.7383], + [1385510400000, 0.7356], + [1385596800000, 0.7358], + [1385683200000, 0.7348], + [1385942400000, 0.7389], + [1386028800000, 0.7366], + [1386115200000, 0.7358], + [1386201600000, 0.7357], + [1386288000000, 0.7321], + [1386547200000, 0.7289], + [1386633600000, 0.7274], + [1386720000000, 0.7265], + [1386806400000, 0.7261], + [1386892800000, 0.7286], + [1387152000000, 0.726], + [1387238400000, 0.7274], + [1387324800000, 0.7274], + [1387411200000, 0.7318], + [1387497600000, 0.7324], + [1387756800000, 0.7299], + [1387843200000, 0.7309], + [1388102400000, 0.724], + [1388361600000, 0.7256], + [1388448000000, 0.7252], + [1388620800000, 0.7323], + [1388707200000, 0.7336], + [1388966400000, 0.7353], + [1389052800000, 0.7332], + [1389139200000, 0.7357], + [1389225600000, 0.7347], + [1389312000000, 0.7361], + [1389571200000, 0.7325], + [1389657600000, 0.7318], + [1389744000000, 0.7351], + [1389830400000, 0.7356], + [1389916800000, 0.7363], + [1390176000000, 0.7372], + [1390262400000, 0.7394], + [1390348800000, 0.7372], + [1390435200000, 0.7333], + [1390521600000, 0.7307], + [1390780800000, 0.7323], + [1390867200000, 0.7328], + [1390953600000, 0.735], + [1391040000000, 0.7368], + [1391126400000, 0.74], + [1391385600000, 0.741], + [1391472000000, 0.7398], + [1391558400000, 0.7385], + [1391644800000, 0.7411], + [1391731200000, 0.7368], + [1391990400000, 0.7333], + [1392076800000, 0.7313], + [1392163200000, 0.7369], + [1392249600000, 0.7314], + [1392336000000, 0.7297], + [1392595200000, 0.7301], + [1392681600000, 0.7284], + [1392768000000, 0.7276], + [1392854400000, 0.7297], + [1392940800000, 0.7297], + [1393200000000, 0.7282], + [1393286400000, 0.7272], + [1393372800000, 0.7286], + [1393459200000, 0.7324], + [1393545600000, 0.7241], + [1393804800000, 0.7264], + [1393891200000, 0.7264], + [1393977600000, 0.7283], + [1394064000000, 0.7276], + [1394150400000, 0.7198], + [1394409600000, 0.7205], + [1394496000000, 0.7221], + [1394582400000, 0.7202], + [1394668800000, 0.7174], + [1394755200000, 0.7204], + [1395014400000, 0.7192], + [1395100800000, 0.7194], + [1395187200000, 0.7189], + [1395273600000, 0.7267], + [1395360000000, 0.7258], + [1395619200000, 0.7261], + [1395705600000, 0.7253], + [1395792000000, 0.7252], + [1395878400000, 0.7269], + [1395964800000, 0.7269], + [1396224000000, 0.7254], + [1396310400000, 0.7253], + [1396396800000, 0.725], + [1396483200000, 0.7263], + [1396569600000, 0.73], + [1396828800000, 0.7288], + [1396915200000, 0.7261], + [1397001600000, 0.7251], + [1397088000000, 0.7212], + [1397174400000, 0.721], + [1397433600000, 0.7233], + [1397520000000, 0.7246], + [1397606400000, 0.7226], + [1397692800000, 0.7219], + [1398124800000, 0.7238], + [1398211200000, 0.723], + [1398297600000, 0.7237], + [1398384000000, 0.7231], + [1398643200000, 0.7215], + [1398729600000, 0.7234], + [1398816000000, 0.7221], + [1398988800000, 0.7215], + [1399248000000, 0.7209], + [1399334400000, 0.7172], + [1399420800000, 0.7181], + [1399507200000, 0.7168], + [1399593600000, 0.7257], + [1399852800000, 0.7266], + [1399939200000, 0.7299], + [1400025600000, 0.729], + [1400112000000, 0.7322], + [1400198400000, 0.7302], + [1400457600000, 0.7292], + [1400544000000, 0.7299], + [1400630400000, 0.7313], + [1400716800000, 0.7317], + [1400803200000, 0.7338], + [1401062400000, 0.7335], + [1401148800000, 0.7333], + [1401235200000, 0.735], + [1401321600000, 0.7347], + [1401408000000, 0.735], + [1401667200000, 0.7348], + [1401753600000, 0.733], + [1401840000000, 0.7339], + [1401926400000, 0.7372], + [1402012800000, 0.7331], + [1402272000000, 0.735], + [1402358400000, 0.7383], + [1402444800000, 0.7383], + [1402531200000, 0.7393], + [1402617600000, 0.739], + [1402876800000, 0.7391], + [1402963200000, 0.7371], + [1403049600000, 0.7374], + [1403136000000, 0.7343], + [1403222400000, 0.736], + [1403481600000, 0.7356], + [1403568000000, 0.7344], + [1403654400000, 0.7346], + [1403740800000, 0.7351], + [1403827200000, 0.7343], + [1404086400000, 0.7323], + [1404172800000, 0.7307], + [1404259200000, 0.7324], + [1404345600000, 0.7329], + [1404432000000, 0.736], + [1404691200000, 0.7358], + [1404777600000, 0.736], + [1404864000000, 0.7352], + [1404950400000, 0.7352], + [1405036800000, 0.7357], + [1405296000000, 0.7339], + [1405382400000, 0.7347], + [1405468800000, 0.7391], + [1405555200000, 0.7395], + [1405641600000, 0.7395], + [1405900800000, 0.7399], + [1405987200000, 0.7419], + [1406073600000, 0.7428], + [1406160000000, 0.7424], + [1406246400000, 0.7441], + [1406505600000, 0.7445], + [1406592000000, 0.7448], + [1406678400000, 0.7463], + [1406764800000, 0.7475], + [1406851200000, 0.7466], + [1407110400000, 0.7451], + [1407196800000, 0.7474], + [1407283200000, 0.7494], + [1407369600000, 0.7482], + [1407456000000, 0.747], + [1407715200000, 0.7471], + [1407801600000, 0.7494], + [1407888000000, 0.7486], + [1407974400000, 0.7479], + [1408060800000, 0.747], + [1408320000000, 0.7473], + [1408406400000, 0.7489], + [1408492800000, 0.7529], + [1408579200000, 0.7541], + [1408665600000, 0.7538], + [1408924800000, 0.7577], + [1409011200000, 0.7581], + [1409097600000, 0.759], + [1409184000000, 0.7589], + [1409270400000, 0.7584], + [1409529600000, 0.7615], + [1409616000000, 0.7626], + [1409702400000, 0.7605], + [1409788800000, 0.7684], + [1409875200000, 0.7724], + [1410134400000, 0.7725], + [1410220800000, 0.7752], + [1410307200000, 0.7736], + [1410393600000, 0.7736], + [1410480000000, 0.7734], + [1410739200000, 0.7746], + [1410825600000, 0.7724], + [1410912000000, 0.7719], + [1410998400000, 0.777], + [1411084800000, 0.7782], + [1411344000000, 0.7786], + [1411430400000, 0.7758], + [1411516800000, 0.7798], + [1411603200000, 0.7868], + [1411689600000, 0.7855], + [1411948800000, 0.7874], + [1412035200000, 0.7948], + [1412121600000, 0.7936], + [1412208000000, 0.7918], + [1412294400000, 0.7927], + [1412553600000, 0.796], + [1412640000000, 0.7933], + [1412726400000, 0.7909], + [1412812800000, 0.7836], + [1412899200000, 0.7914], + [1413158400000, 0.7888], + [1413244800000, 0.7909], + [1413331200000, 0.7896], + [1413417600000, 0.7845], + [1413504000000, 0.7799], + [1413763200000, 0.783], + [1413849600000, 0.7837], + [1413936000000, 0.7879], + [1414022400000, 0.7894], + [1414108800000, 0.7901], + [1414368000000, 0.7888], + [1414454400000, 0.7845], + [1414540800000, 0.7852], + [1414627200000, 0.7939], + [1414713600000, 0.7986], + [1414972800000, 0.8005], + [1415059200000, 0.7992], + [1415145600000, 0.8014], + [1415232000000, 0.799], + [1415318400000, 0.807], + [1415577600000, 0.801], + [1415664000000, 0.805], + [1415750400000, 0.8022], + [1415836800000, 0.8029], + [1415923200000, 0.8042], + [1416182400000, 0.8004], + [1416268800000, 0.7992], + [1416355200000, 0.7979], + [1416441600000, 0.7976], + [1416528000000, 0.8051], + [1416787200000, 0.8059], + [1416873600000, 0.805], + [1416960000000, 0.8017], + [1417046400000, 0.8014], + [1417132800000, 0.8012], + [1417392000000, 0.8021], + [1417478400000, 0.805], + [1417564800000, 0.8111], + [1417651200000, 0.8124], + [1417737600000, 0.809], + [1417996800000, 0.8159], + [1418083200000, 0.8086], + [1418169600000, 0.8071], + [1418256000000, 0.8047], + [1418342400000, 0.8033], + [1418601600000, 0.8049], + [1418688000000, 0.7977], + [1418774400000, 0.8034], + [1418860800000, 0.8141], + [1418947200000, 0.8145], + [1419206400000, 0.8158], + [1419292800000, 0.8189], + [1419379200000, 0.8185], + [1419811200000, 0.82], + [1419897600000, 0.8225], + [1419984000000, 0.8238], + [1420156800000, 0.8305], + [1420416000000, 0.8394], + [1420502400000, 0.8394], + [1420588800000, 0.8453], + [1420675200000, 0.8499], + [1420761600000, 0.8466], + [1421020800000, 0.8473], + [1421107200000, 0.8489], + [1421193600000, 0.8494], + [1421280000000, 0.8542], + [1421366400000, 0.8631], + [1421625600000, 0.8618], + [1421712000000, 0.8637], + [1421798400000, 0.8627], + [1421884800000, 0.8608], + [1421971200000, 0.8931], + [1422230400000, 0.8895], + [1422316800000, 0.8846], + [1422403200000, 0.8816], + [1422489600000, 0.8839], + [1422576000000, 0.8847], + [1422835200000, 0.8843], + [1422921600000, 0.8791], + [1423008000000, 0.8738], + [1423094400000, 0.8765], + [1423180800000, 0.8737], + [1423440000000, 0.887], + [1423526400000, 0.8853], + [1423612800000, 0.884], + [1423699200000, 0.8829], + [1423785600000, 0.8788], + [1424044800000, 0.8767], + [1424131200000, 0.8761], + [1424217600000, 0.8795], + [1424304000000, 0.8783], + [1424390400000, 0.8852], + [1424649600000, 0.8852], + [1424736000000, 0.8829], + [1424822400000, 0.8815], + [1424908800000, 0.8837], + [1424995200000, 0.8898], + [1425254400000, 0.8908], + [1425340800000, 0.8955], + [1425427200000, 0.8991], + [1425513600000, 0.9035], + [1425600000000, 0.9123], + [1425859200000, 0.9209], + [1425945600000, 0.9314], + [1426032000000, 0.9455], + [1426118400000, 0.9423], + [1426204800000, 0.946], + [1426464000000, 0.9473], + [1426550400000, 0.9404], + [1426636800000, 0.9442], + [1426723200000, 0.9367], + [1426809600000, 0.9281], + [1427068800000, 0.9165], + [1427155200000, 0.9133], + [1427241600000, 0.9104], + [1427328000000, 0.9114], + [1427414400000, 0.9212], + [1427673600000, 0.9222], + [1427760000000, 0.9296], + [1427846400000, 0.9299], + [1427932800000, 0.9235], + [1428364800000, 0.922], + [1428451200000, 0.9207], + [1428537600000, 0.9283], + [1428624000000, 0.9462], + [1428883200000, 0.9478], + [1428969600000, 0.9467], + [1429056000000, 0.9454], + [1429142400000, 0.9337], + [1429228800000, 0.9248], + [1429488000000, 0.9327], + [1429574400000, 0.9347], + [1429660800000, 0.9309], + [1429747200000, 0.9284], + [1429833600000, 0.924], + [1430092800000, 0.9241], + [1430179200000, 0.9153], + [1430265600000, 0.909], + [1430352000000, 0.8918], + [1430697600000, 0.8968], + [1430784000000, 0.8996], + [1430870400000, 0.8906], + [1430956800000, 0.8847], + [1431043200000, 0.8913], + [1431302400000, 0.8976], + [1431388800000, 0.8899], + [1431475200000, 0.8913], + [1431561600000, 0.8758], + [1431648000000, 0.8829], + [1431907200000, 0.8781], + [1431993600000, 0.8946], + [1432080000000, 0.8995], + [1432166400000, 0.8983], + [1432252800000, 0.8958], + [1432512000000, 0.911], + [1432598400000, 0.9153], + [1432684800000, 0.9207], + [1432771200000, 0.9179], + [1432857600000, 0.9117], + [1433116800000, 0.9138], + [1433203200000, 0.9068], + [1433289600000, 0.8982], + [1433376000000, 0.8837], + [1433462400000, 0.8915], + [1433721600000, 0.896], + [1433808000000, 0.8891], + [1433894400000, 0.8867], + [1433980800000, 0.8904], + [1434067200000, 0.8914], + [1434326400000, 0.8915], + [1434412800000, 0.8918], + [1434499200000, 0.8867], + [1434585600000, 0.877], + [1434672000000, 0.8851], + [1434931200000, 0.8815], + [1435017600000, 0.8926], + [1435104000000, 0.8919], + [1435190400000, 0.8925], + [1435276800000, 0.8928], + [1435536000000, 0.8983], + [1435622400000, 0.8938], + [1435708800000, 0.901], + [1435795200000, 0.9038], + [1435881600000, 0.9013], + [1436140800000, 0.9085], + [1436227200000, 0.9149], + [1436313600000, 0.9072], + [1436400000000, 0.9047], + [1436486400000, 0.8942], + [1436745600000, 0.9052], + [1436832000000, 0.9066], + [1436918400000, 0.9084], + [1437004800000, 0.9203], + [1437091200000, 0.9185], + [1437350400000, 0.9216], + [1437436800000, 0.9203], + [1437523200000, 0.9174], + [1437609600000, 0.9093], + [1437696000000, 0.9143], + [1437955200000, 0.9044], + [1438041600000, 0.9071], + [1438128000000, 0.9067], + [1438214400000, 0.9129], + [1438300800000, 0.9119], + [1438560000000, 0.9133], + [1438646400000, 0.9114], + [1438732800000, 0.919], + [1438819200000, 0.9188], + [1438905600000, 0.9141], + [1439164800000, 0.9125], + [1439251200000, 0.9047], + [1439337600000, 0.8966], + [1439424000000, 0.9003], + [1439510400000, 0.8953], + [1439769600000, 0.901], + [1439856000000, 0.9043], + [1439942400000, 0.9058], + [1440028800000, 0.8943], + [1440115200000, 0.8865], + [1440374400000, 0.8699], + [1440460800000, 0.8692], + [1440547200000, 0.8771], + [1440633600000, 0.8863], + [1440720000000, 0.8876], + [1440979200000, 0.8918], + [1441065600000, 0.8901], + [1441152000000, 0.8886], + [1441238400000, 0.8907], + [1441324800000, 0.8979], + [1441584000000, 0.8973], + [1441670400000, 0.896], + [1441756800000, 0.8978], + [1441843200000, 0.8942], + [1441929600000, 0.8876], + [1442188800000, 0.8847], + [1442275200000, 0.8835], + [1442361600000, 0.8907], + [1442448000000, 0.8841], + [1442534400000, 0.8758], + [1442793600000, 0.889], + [1442880000000, 0.8966], + [1442966400000, 0.897], + [1443052800000, 0.8897], + [1443139200000, 0.8969], + [1443398400000, 0.8954], + [1443484800000, 0.8926], + [1443571200000, 0.8927], + [1443657600000, 0.8967], + [1443744000000, 0.8962], + [1444003200000, 0.8901], + [1444089600000, 0.891], + [1444176000000, 0.8877], + [1444262400000, 0.8887], + [1444348800000, 0.8802], + [1444608000000, 0.8794], + [1444694400000, 0.8793], + [1444780800000, 0.8765], + [1444867200000, 0.8743], + [1444953600000, 0.8804], + [1445212800000, 0.8825], + [1445299200000, 0.8794], + [1445385600000, 0.8808], + [1445472000000, 0.884], + [1445558400000, 0.9023], + [1445817600000, 0.9083], + [1445904000000, 0.9042], + [1445990400000, 0.9022], + [1446076800000, 0.915], + [1446163200000, 0.9078], + [1446422400000, 0.9066], + [1446508800000, 0.9112], + [1446595200000, 0.9146], + [1446681600000, 0.919], + [1446768000000, 0.9206], + [1447027200000, 0.9281], + [1447113600000, 0.9337], + [1447200000000, 0.9333], + [1447286400000, 0.9324], + [1447372800000, 0.9291], + [1447632000000, 0.9327], + [1447718400000, 0.9373], + [1447804800000, 0.9377], + [1447891200000, 0.9358], + [1447977600000, 0.9357], + [1448236800000, 0.9407], + [1448323200000, 0.939], + [1448409600000, 0.9447], + [1448496000000, 0.9424], + [1448582400000, 0.9453], + [1448841600000, 0.9454], + [1448928000000, 0.9435], + [1449014400000, 0.9424], + [1449100800000, 0.9372], + [1449187200000, 0.9174], + [1449446400000, 0.9253], + [1449532800000, 0.9196], + [1449619200000, 0.9141], + [1449705600000, 0.9139], + [1449792000000, 0.9133], + [1450051200000, 0.9106], + [1450137600000, 0.91], + [1450224000000, 0.9148], + [1450310400000, 0.9225], + [1450396800000, 0.9229], + [1450656000000, 0.9201], + [1450742400000, 0.9132], + [1450828800000, 0.9162], + [1450915200000, 0.9136], + [1451260800000, 0.9123], + [1451347200000, 0.9132], + [1451433600000, 0.9153], + [1451520000000, 0.9186], + [1451865600000, 0.9177], + [1451952000000, 0.9307], + [1452038400000, 0.931], + [1452124800000, 0.9202], + [1452211200000, 0.9208], + [1452470400000, 0.9185], + [1452556800000, 0.9229], + [1452643200000, 0.9247], + [1452729600000, 0.9181], + [1452816000000, 0.9164], + [1453075200000, 0.9182], + [1453161600000, 0.9202], + [1453248000000, 0.9169], + [1453334400000, 0.9181], + [1453420800000, 0.9253], + [1453680000000, 0.9247], + [1453766400000, 0.9229], + [1453852800000, 0.9185], + [1453939200000, 0.9173], + [1454025600000, 0.9159], + [1454284800000, 0.9189], + [1454371200000, 0.9159], + [1454457600000, 0.9148], + [1454544000000, 0.8925], + [1454630400000, 0.8928], + [1454889600000, 0.9009], + [1454976000000, 0.8901], + [1455062400000, 0.8884], + [1455148800000, 0.8814], + [1455235200000, 0.887], + [1455494400000, 0.8946], + [1455580800000, 0.8957], + [1455667200000, 0.8981], + [1455753600000, 0.9023], + [1455840000000, 0.9013], + [1456099200000, 0.907], + [1456185600000, 0.909], + [1456272000000, 0.9108], + [1456358400000, 0.907], + [1456444800000, 0.9087], + [1456704000000, 0.9185], + [1456790400000, 0.9199], + [1456876800000, 0.9212], + [1456963200000, 0.9174], + [1457049600000, 0.9117], + [1457308800000, 0.9131], + [1457395200000, 0.9069], + [1457481600000, 0.9114], + [1457568000000, 0.9212], + [1457654400000, 0.9018], + [1457913600000, 0.8995], + [1458000000000, 0.9003], + [1458086400000, 0.9039], + [1458172800000, 0.8842], + [1458259200000, 0.8867], + [1458518400000, 0.8873], + [1458604800000, 0.892], + [1458691200000, 0.8953], + [1458777600000, 0.8966], + [1459209600000, 0.8934], + [1459296000000, 0.8832], + [1459382400000, 0.8784], + [1459468800000, 0.8748], + [1459728000000, 0.8788], + [1459814400000, 0.8798], + [1459900800000, 0.8822], + [1459987200000, 0.8801], + [1460073600000, 0.8801], + [1460332800000, 0.8781], + [1460419200000, 0.8776], + [1460505600000, 0.8852], + [1460592000000, 0.8888], + [1460678400000, 0.8863], + [1460937600000, 0.8846], + [1461024000000, 0.8817], + [1461110400000, 0.8789], + [1461196800000, 0.8808], + [1461283200000, 0.888], + [1461542400000, 0.8879], + [1461628800000, 0.8861], + [1461715200000, 0.8848], + [1461801600000, 0.8805], + [1461888000000, 0.8771], + [1462147200000, 0.8702], + [1462233600000, 0.8645], + [1462320000000, 0.8693], + [1462406400000, 0.8743], + [1462492800000, 0.8752], + [1462752000000, 0.8777], + [1462838400000, 0.8792], + [1462924800000, 0.8766], + [1463011200000, 0.8781], + [1463097600000, 0.8813], + [1463356800000, 0.8832], + [1463443200000, 0.8836], + [1463529600000, 0.8867], + [1463616000000, 0.8932], + [1463702400000, 0.8914], + [1463961600000, 0.8918], + [1464048000000, 0.8955], + [1464134400000, 0.8973], + [1464220800000, 0.8955], + [1464307200000, 0.8955], + [1464566400000, 0.8978], + [1464652800000, 0.8966], + [1464739200000, 0.895], + [1464825600000, 0.8939], + [1464912000000, 0.8966], + [1465171200000, 0.8812], + [1465257600000, 0.8813], + [1465344000000, 0.879], + [1465430400000, 0.8817], + [1465516800000, 0.8847], + [1465776000000, 0.8876], + [1465862400000, 0.891], + [1465948800000, 0.8906], + [1466035200000, 0.895], + [1466121600000, 0.8887], + [1466380800000, 0.8826], + [1466467200000, 0.884], + [1466553600000, 0.8864], + [1466640000000, 0.8781], + [1466726400000, 0.9038], + [1466985600000, 0.9094], + [1467072000000, 0.9032], + [1467158400000, 0.9018], + [1467244800000, 0.9008], + [1467331200000, 0.8982], + [1467590400000, 0.8979], + [1467676800000, 0.8973], + [1467763200000, 0.9035], + [1467849600000, 0.9026], + [1467936000000, 0.9034], + [1468195200000, 0.9052], + [1468281600000, 0.9017], + [1468368000000, 0.9033], + [1468454400000, 0.8964], + [1468540800000, 0.8987], + [1468800000000, 0.9048], + [1468886400000, 0.9063], + [1468972800000, 0.9081], + [1469059200000, 0.908], + [1469145600000, 0.908], + [1469404800000, 0.9107], + [1469491200000, 0.9094], + [1469577600000, 0.9099], + [1469664000000, 0.9018], + [1469750400000, 0.8999], + [1470009600000, 0.8958], + [1470096000000, 0.8935], + [1470182400000, 0.893], + [1470268800000, 0.8981], + [1470355200000, 0.8965], + [1470614400000, 0.9021], + [1470700800000, 0.9028], + [1470787200000, 0.8942], + [1470873600000, 0.8967], + [1470960000000, 0.8963], + [1471219200000, 0.8946], + [1471305600000, 0.8854], + [1471392000000, 0.8869], + [1471478400000, 0.8834], + [1471564800000, 0.883], + [1471824000000, 0.8846], + [1471910400000, 0.882], + [1471996800000, 0.8876], + [1472083200000, 0.8858], + [1472169600000, 0.8858], + [1472428800000, 0.8954], + [1472515200000, 0.8955], + [1472601600000, 0.8984], + [1472688000000, 0.8973], + [1472774400000, 0.8935], + [1473033600000, 0.8965], + [1473120000000, 0.8962], + [1473206400000, 0.89], + [1473292800000, 0.8854], + [1473379200000, 0.8876], + [1473638400000, 0.8909], + [1473724800000, 0.8892], + [1473811200000, 0.8915], + [1473897600000, 0.8887], + [1473984000000, 0.8909], + [1474243200000, 0.8958], + [1474329600000, 0.8942], + [1474416000000, 0.897], + [1474502400000, 0.8899], + [1474588800000, 0.8918], + [1474848000000, 0.888], + [1474934400000, 0.8914], + [1475020800000, 0.891], + [1475107200000, 0.8913], + [1475193600000, 0.8961], + [1475452800000, 0.8901], + [1475539200000, 0.8961], + [1475625600000, 0.8921], + [1475712000000, 0.8942], + [1475798400000, 0.8978], + [1476057600000, 0.8962], + [1476144000000, 0.9027], + [1476230400000, 0.9075], + [1476316800000, 0.9061], + [1476403200000, 0.909], + [1476662400000, 0.9097], + [1476748800000, 0.9098], + [1476835200000, 0.9109], + [1476921600000, 0.9108], + [1477008000000, 0.9187], + [1477267200000, 0.9183], + [1477353600000, 0.9199], + [1477440000000, 0.9154], + [1477526400000, 0.9153], + [1477612800000, 0.9157], + [1477872000000, 0.9137], + [1477958400000, 0.9071], + [1478044800000, 0.9014], + [1478131200000, 0.9039], + [1478217600000, 0.9016], + [1478476800000, 0.9041], + [1478563200000, 0.9061], + [1478649600000, 0.9074], + [1478736000000, 0.918], + [1478822400000, 0.9172], + [1479081600000, 0.928], + [1479168000000, 0.929], + [1479254400000, 0.9345], + [1479340800000, 0.9332], + [1479427200000, 0.9409], + [1479686400000, 0.9407], + [1479772800000, 0.942], + [1479859200000, 0.9433], + [1479945600000, 0.9481], + [1480032000000, 0.9442], + [1480291200000, 0.9446], + [1480377600000, 0.9456], + [1480464000000, 0.9404], + [1480550400000, 0.9411], + [1480636800000, 0.9398], + [1480896000000, 0.9345], + [1480982400000, 0.9317], + [1481068800000, 0.9321], + [1481155200000, 0.9293], + [1481241600000, 0.9472], + [1481500800000, 0.9439], + [1481587200000, 0.9426], + [1481673600000, 0.9396], + [1481760000000, 0.9599], + [1481846400000, 0.958], + [1482105600000, 0.9596], + [1482192000000, 0.965], + [1482278400000, 0.9597], + [1482364800000, 0.9576], + [1482451200000, 0.9574], + [1482796800000, 0.9575], + [1482883200000, 0.9615], + [1482969600000, 0.9568], + [1483056000000, 0.9488], + [1483315200000, 0.9557], + [1483401600000, 0.963], + [1483488000000, 0.9582], + [1483574400000, 0.9524], + [1483660800000, 0.9445], + [1483920000000, 0.951], + [1484006400000, 0.9464], + [1484092800000, 0.9522], + [1484179200000, 0.9365], + [1484265600000, 0.9381], + [1484524800000, 0.944], + [1484611200000, 0.9361], + [1484697600000, 0.9378], + [1484784000000, 0.9375], + [1484870400000, 0.9407], + [1485129600000, 0.9334], + [1485216000000, 0.9305], + [1485302400000, 0.9309], + [1485388800000, 0.9347], + [1485475200000, 0.9363], + [1485734400000, 0.9408], + [1485820800000, 0.9299], + [1485907200000, 0.9269], + [1485993600000, 0.9253], + [1486080000000, 0.9311], + [1486339200000, 0.9336], + [1486425600000, 0.9369], + [1486512000000, 0.9377], + [1486598400000, 0.9354], + [1486684800000, 0.9409], + [1486944000000, 0.9409], + [1487030400000, 0.9415], + [1487116800000, 0.9475], + [1487203200000, 0.9389], + [1487289600000, 0.9391], + [1487548800000, 0.9421], + [1487635200000, 0.9491], + [1487721600000, 0.9513], + [1487808000000, 0.9459], + [1487894400000, 0.9427], + [1488153600000, 0.9447], + [1488240000000, 0.9438], + [1488326400000, 0.9495], + [1488412800000, 0.9512], + [1488499200000, 0.9466], + [1488758400000, 0.9442], + [1488844800000, 0.9456], + [1488931200000, 0.9474], + [1489017600000, 0.9479], + [1489104000000, 0.943], + [1489363200000, 0.9379], + [1489449600000, 0.9407], + [1489536000000, 0.9415], + [1489622400000, 0.9324], + [1489708800000, 0.9315], + [1489968000000, 0.9302], + [1490054400000, 0.9259], + [1490140800000, 0.9254], + [1490227200000, 0.9272], + [1490313600000, 0.9256], + [1490572800000, 0.9185], + [1490659200000, 0.921], + [1490745600000, 0.9305], + [1490832000000, 0.9315], + [1490918400000, 0.9355], + [1491177600000, 0.9381], + [1491264000000, 0.939], + [1491350400000, 0.9366], + [1491436800000, 0.9377], + [1491523200000, 0.9408], + [1491782400000, 0.9455], + [1491868800000, 0.9421], + [1491955200000, 0.9431], + [1492041600000, 0.9408], + [1492473600000, 0.9363], + [1492560000000, 0.9325], + [1492646400000, 0.9308], + [1492732800000, 0.9349], + [1492992000000, 0.9219], + [1493078400000, 0.9183], + [1493164800000, 0.9181], + [1493251200000, 0.9191], + [1493337600000, 0.915], + [1493683200000, 0.9163], + [1493769600000, 0.9159], + [1493856000000, 0.9153], + [1493942400000, 0.9124], + [1494201600000, 0.9143], + [1494288000000, 0.9185], + [1494374400000, 0.919], + [1494460800000, 0.9209], + [1494547200000, 0.9196], + [1494806400000, 0.9115], + [1494892800000, 0.9043], + [1494979200000, 0.8996], + [1495065600000, 0.8987], + [1495152000000, 0.8946], + [1495411200000, 0.8895], + [1495497600000, 0.8918], + [1495584000000, 0.8935], + [1495670400000, 0.8918], + [1495756800000, 0.8933], + [1496016000000, 0.8939], + [1496102400000, 0.8951], + [1496188800000, 0.8913], + [1496275200000, 0.8914], + [1496361600000, 0.8916], + [1496620800000, 0.8891], + [1496707200000, 0.8884], + [1496793600000, 0.8916], + [1496880000000, 0.8907], + [1496966400000, 0.8949], + [1497225600000, 0.8913], + [1497312000000, 0.8916], + [1497398400000, 0.8927], + [1497484800000, 0.8957], + [1497571200000, 0.8956], + [1497830400000, 0.893], + [1497916800000, 0.8965], + [1498003200000, 0.8972], + [1498089600000, 0.8954], + [1498176000000, 0.8951], + [1498435200000, 0.894], + [1498521600000, 0.8868], + [1498608000000, 0.8792], + [1498694400000, 0.8763], + [1498780800000, 0.8764], + [1499040000000, 0.8797], + [1499126400000, 0.8809], + [1499212800000, 0.8828], + [1499299200000, 0.8784], + [1499385600000, 0.8764], + [1499644800000, 0.8783], + [1499731200000, 0.8769], + [1499817600000, 0.8735], + [1499904000000, 0.876], + [1499990400000, 0.8761], + [1500249600000, 0.8725], + [1500336000000, 0.8655], + [1500422400000, 0.8672], + [1500508800000, 0.8708], + [1500595200000, 0.8591], + [1500854400000, 0.8586], + [1500940800000, 0.8552], + [1501027200000, 0.8589], + [1501113600000, 0.8552], + [1501200000000, 0.8527], + [1501459200000, 0.8528], + [1501545600000, 0.8467], + [1501632000000, 0.8455], + [1501718400000, 0.8433], + [1501804800000, 0.8427], + [1502064000000, 0.8478], + [1502150400000, 0.8466], + [1502236800000, 0.8525], + [1502323200000, 0.8525], + [1502409600000, 0.8501], + [1502668800000, 0.8478], + [1502755200000, 0.8516], + [1502841600000, 0.8541], + [1502928000000, 0.855], + [1503014400000, 0.8519], + [1503273600000, 0.8504], + [1503360000000, 0.8496], + [1503446400000, 0.8476], + [1503532800000, 0.8471], + [1503619200000, 0.847], + [1503878400000, 0.8387], + [1503964800000, 0.8301], + [1504051200000, 0.8393], + [1504137600000, 0.8458], + [1504224000000, 0.839], + [1504483200000, 0.8401], + [1504569600000, 0.8411], + [1504656000000, 0.8383], + [1504742400000, 0.8355], + [1504828800000, 0.8293], + [1505088000000, 0.8336], + [1505174400000, 0.8381], + [1505260800000, 0.8349], + [1505347200000, 0.8415], + [1505433600000, 0.836], + [1505692800000, 0.8371], + [1505779200000, 0.8354], + [1505865600000, 0.8329], + [1505952000000, 0.8401], + [1506038400000, 0.8362], + [1506297600000, 0.8428], + [1506384000000, 0.8485], + [1506470400000, 0.8518], + [1506556800000, 0.8491], + [1506643200000, 0.8471], + [1506902400000, 0.8516], + [1506988800000, 0.8509], + [1507075200000, 0.8485], + [1507161600000, 0.8517], + [1507248000000, 0.8543], + [1507507200000, 0.8515], + [1507593600000, 0.8478], + [1507680000000, 0.8454], + [1507766400000, 0.8436], + [1507852800000, 0.8468], + [1508112000000, 0.8473], + [1508198400000, 0.8505], + [1508284800000, 0.8512], + [1508371200000, 0.8451], + [1508457600000, 0.8463], + [1508716800000, 0.8519], + [1508803200000, 0.8504], + [1508889600000, 0.8486], + [1508976000000, 0.8509], + [1509062400000, 0.8618], + [1509321600000, 0.8613], + [1509408000000, 0.8594], + [1509494400000, 0.8613], + [1509580800000, 0.8588], + [1509667200000, 0.858], + [1509926400000, 0.8629], + [1510012800000, 0.865], + [1510099200000, 0.8629], + [1510185600000, 0.8599], + [1510272000000, 0.8582], + [1510531200000, 0.858], + [1510617600000, 0.8515], + [1510704000000, 0.8447], + [1510790400000, 0.8496], + [1510876800000, 0.8479], + [1511136000000, 0.8489], + [1511222400000, 0.8535], + [1511308800000, 0.8512], + [1511395200000, 0.8441], + [1511481600000, 0.8421], + [1511740800000, 0.8368], + [1511827200000, 0.8413], + [1511913600000, 0.8456], + [1512000000000, 0.8441], + [1512086400000, 0.8415], + [1512345600000, 0.8429], + [1512432000000, 0.8442], + [1512518400000, 0.8463], + [1512604800000, 0.8486], + [1512691200000, 0.8517], + [1512950400000, 0.8478], + [1513036800000, 0.85], + [1513123200000, 0.8522], + [1513209600000, 0.8443], + [1513296000000, 0.8471], + [1513555200000, 0.8479], + [1513641600000, 0.8459], + [1513728000000, 0.8443], + [1513814400000, 0.8433], + [1513900800000, 0.8438], + [1514332800000, 0.8408], + [1514419200000, 0.838], + [1514505600000, 0.8339], +]; diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 54d1a57572..b29d906c1f 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -7,7 +7,7 @@ import {SidebarCategoryRoutes} from '../../../constants'; import ComponentPageLayout from '../../../layouts/ComponentPageLayout'; import {getFeature, getNavigationData} from '../../../utils/api'; import {ExamplesDataVizBaseChart as BaseChart} from '../../../component-examples/data-visualization/BaseChart'; -import {CustomChartProviderExample, SimpleChartProviderExample} from '../../../component-examples/data-visualization/ChartProviderExamples'; +import {CustomChartProviderExample, DefaultAreaExample, DefaultColumnExample, DefaultLineExample, SimpleChartProviderExample} from '../../../component-examples/data-visualization/ChartExamples'; export const meta = { title: 'Chart Provider', @@ -56,6 +56,42 @@ We highly recommend using our [BaseChart](/foundations/data-visualization/engine ## Examples +### Line Chart + +Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/engineering/chart-types#line). + + +{DefaultLineExample} + + +### Area Chart + +Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/engineering/chart-types#area). + + +{DefaultAreaExample} + + +### Column Chart + +Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/engineering/chart-types#column). + + +{DefaultColumnExample} + + ### Custom charts You can use the `highchartsOptions` to create unsupported charts by passing the Higcharts config directly to the base chart without modification. We recommend using our wrappers for easier migration and a simpler way of accessing the rendered chart object for building custom interactions. diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx index 36ee511c35..27965ff22a 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx @@ -22,8 +22,9 @@ import { InlineCode } from "@twilio-paste/inline-code"; import { SidebarCategoryRoutes } from "../../../../constants"; import DefaultLayout from "../../../../layouts/DefaultLayout"; import { getNavigationData } from "../../../../utils/api"; -import { CustomChartProviderExample } from "../../../../component-examples/data-visualization/ChartProviderExamples"; +import { CustomChartProviderExample, AreaTimeSeriesPanZoomExample, DefaultAreaExample, DefaultLineExample, LineTimeSeriesPanZoomExample, DefaultColumnExample, ColumnStackedNormalExample, ColumnStackedPercentExample, ColumnGroupedAxisExample } from "../../../../component-examples/data-visualization/ChartExamples"; import { ExamplesDataVizBaseChart as BaseChart } from "../../../../component-examples/data-visualization/BaseChart"; +import {usdEurData} from "../../../../component-examples/data-visualization/usdEurData"; export default DefaultLayout; @@ -55,8 +56,99 @@ export const getStaticProps = async () => { -### Custom +## Line +### Default Line + + +{DefaultLineExample} + + +### Zoom & Pan on Time-Based X Axis Line + + +{LineTimeSeriesPanZoomExample} + + +## Area + +### Default Area + + +{DefaultAreaExample} + + +### Zoom & Pan on Time-Based X Axis Area + + +{AreaTimeSeriesPanZoomExample} + + +## Column + +### Default Column + + +{DefaultColumnExample} + + +### Stacked - Normal + + +{ColumnStackedNormalExample} + + +### Stacked - Percentage + + +{ColumnStackedPercentExample} + + +### X Axis Categories Column + + +{ColumnGroupedAxisExample} + + +## Custom + +You can still use our chart wrappers and base components while leveraging raw Highcharts options instead of our predefined ones. This gives you the flexibility to build custom charts and include features that aren’t currently supported by our components. + +### Unsupported options + +The chart below demonstrates a combination of line and column series—this series type isn’t currently supported by our components. It also applies title styling using Highcharts options, which falls outside of what our components currently handle. Date: Fri, 25 Apr 2025 10:12:16 -0500 Subject: [PATCH 34/54] feat(data-visualization): jsdoc and type cleanup --- .../transformers/columnChart.spec.tsx | 1 - .../src/transformers/columnChart.ts | 6 +- .../data-visualization/src/types.ts | 79 ++++++++++++++++++- .../stories/supported-charts.stories.tsx | 44 +++++------ 4 files changed, 100 insertions(+), 30 deletions(-) diff --git a/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx b/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx index b492a74e5b..d48a7278c1 100644 --- a/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx +++ b/packages/paste-libraries/data-visualization/__test__/transformers/columnChart.spec.tsx @@ -77,7 +77,6 @@ describe("Column Chart Transformer", () => { ...options, xAxisCategories, stackingType: "normal", - showStackedLabels: true, showDataLabels: true, }), { wrapper: container }, diff --git a/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts b/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts index 125b817542..b3d8965626 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts @@ -8,12 +8,10 @@ export const handleColumnOptions = ({ series, type, stackingType, - xAxisCategories, showDataLabels, - showStackedLabels, ...baseChartProps }: ColumnChartConfig): Highcharts.Options => { - const { xAxis, yAxis, ...rest } = handleBaseChartOptionsFormatting({ + const { yAxis, ...rest } = handleBaseChartOptionsFormatting({ ...baseChartProps, type, }); @@ -31,7 +29,7 @@ export const handleColumnOptions = ({ yAxis: Highcharts.merge( { stackLabels: { - enabled: showStackedLabels, + enabled: showDataLabels, }, }, yAxis, diff --git a/packages/paste-libraries/data-visualization/src/types.ts b/packages/paste-libraries/data-visualization/src/types.ts index 67904c7937..c34cef9170 100644 --- a/packages/paste-libraries/data-visualization/src/types.ts +++ b/packages/paste-libraries/data-visualization/src/types.ts @@ -25,41 +25,114 @@ export type ColumnSeries = Pick< type ChartConfig = Pick; -type ChartAccessibilityConfig = Pick; +type ChartAccessibilityConfig = Pick< + Highcharts.AccessibilityOptions, + "description" | "point" | "linkedDescription" | "series" +>; interface TitleConfig extends Pick { hide?: boolean; } - export interface BaseChartOptions { + /** + * Sets metadata for the chart such as whether it is animated, the height and width of the chart, and other chart options. + */ chart?: ChartConfig; + /** + * Sets global accessiblity options such as formatting the point and series text that is read to users when they focus on elements. + */ accessibility?: ChartAccessibilityConfig; + /** + * Configure the title of the chart. Optionall hide the title too. The purpose of setting text but hiding the title allows the + * title to still be included in any chart descritions read by screen readers. + */ title?: TitleConfig; + /** + * Configure the sub title of the chart. Optionall hide the sub title too. The purpose of setting text but hiding the sub title allows the + * sub title to still be included in any chart descritions read by screen readers. + */ subtitle?: TitleConfig; + /** + * The type of chart to render. This will determine what other chart specfic options are available. + */ type: SupportedCharts; + /** + * Render the X axis as a datetime. + */ isXTimeAxis?: boolean; + /** + * Whether to show the native legend provided by Highcharts. + */ showLegend?: boolean; + /** + * The type of zooming to enable on the chart. This will determine whether users can zoom in the x, y or both axis. + */ zoomingType?: Highcharts.ChartOptions["zoomType"]; + /** + * The type of panning to enable on the chart allowing users to move the region currently zoomed in on. + * This will determine whether users can pan in the x, y or both axis. + */ panningType?: Highcharts.ChartOptions["zoomType"]; + /** + * A function that formats the point text for Highcharts native tooltips. + */ pointFormatter?: (point: Highcharts.Point) => string; + /** + * Configure the y axis of the chart. Optionall hide the y axis too. The purpose of setting text but hiding the y axis allows the + * y axis to still be included in any chart descritions read by screen readers. + */ yAxisTitle?: TitleConfig; + /** + * Configure the x axis of the chart. Optionall hide the x axis too. The purpose of setting text but hiding the x axis allows the + * x axis to still be included in any chart descritions read by screen readers. + */ xAxisTitle?: TitleConfig; + /** + * Controls the display of teh watermark in the bottom right of the chart accrediting Highcharts. Not needed for projects with a license and disbaled by default. + * + * @default false + */ enableCredits?: boolean; + /** + * Controls whether the chart is animated. + * + * @default true + */ isAnimated?: boolean; + /** + * The data to be displayed on the x axis labels. This is useful when you do not have the x plot data in your series but need to set the tick labels on teh x axis. + */ xAxisCategories?: Highcharts.XAxisOptions["categories"]; } export interface LineChartConfig extends BaseChartOptions { + /** + * The series data for a line chart. + */ series: LineSeries[]; + /** + * Specifies that this is a line chart. + */ type: "line"; } export interface ColumnChartConfig extends BaseChartOptions { + /** + * The series data for a column chart. + */ series: ColumnSeries[]; + /** + * Specifies that this is a column chart. + */ type: "column"; + /** + * The type of stacking to use for the column chart, whether to show percentage stacked or normal. + */ stackingType?: "normal" | "percent"; - showStackedLabels?: boolean; + /** + * Show the number value for the column on top of the section. Works for regular and stacked variants. + */ showDataLabels?: boolean; } diff --git a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx index c0b00016a0..38b06d8c7a 100644 --- a/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx +++ b/packages/paste-libraries/data-visualization/stories/supported-charts.stories.tsx @@ -40,15 +40,27 @@ export const Line: StoryFn = () => { ); }; -export const Column: StoryFn = () => { +export const LineZoomPanningTimeSeries: StoryFn = () => { return ( @@ -58,7 +70,7 @@ export const Column: StoryFn = () => { ); }; -export const ColumnDefinedXAxisCategories: StoryFn = () => { +export const Column: StoryFn = () => { return ( { title: { text: "Fruit popularity", }, - xAxisCategories: ["2020", "2021", "2022", "2023", "2024", "2025"], }} > @@ -77,28 +88,17 @@ export const ColumnDefinedXAxisCategories: StoryFn = () => { ); }; -export const LineZoomPanningTimeSeries: StoryFn = () => { +export const ColumnDefinedXAxisCategories: StoryFn = () => { return ( From e67f1e3efff4524e4ae8f120777bbc8a6c4c47cb Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Fri, 25 Apr 2025 10:26:02 -0500 Subject: [PATCH 35/54] feat(data-visualization): cedits and column styles --- .../src/transformers/columnChart.ts | 1 + .../data-visualization/src/types.ts | 6 ++++++ .../data-visualization/ChartExamples.ts | 18 +++++++++++++++++- .../engineering/chart-types.mdx | 2 +- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts b/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts index b3d8965626..da325df157 100644 --- a/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts +++ b/packages/paste-libraries/data-visualization/src/transformers/columnChart.ts @@ -24,6 +24,7 @@ export const handleColumnOptions = ({ dataLabels: { enabled: showDataLabels, }, + borderRadius: 2, }, }, yAxis: Highcharts.merge( diff --git a/packages/paste-libraries/data-visualization/src/types.ts b/packages/paste-libraries/data-visualization/src/types.ts index c34cef9170..77f5f542a3 100644 --- a/packages/paste-libraries/data-visualization/src/types.ts +++ b/packages/paste-libraries/data-visualization/src/types.ts @@ -137,7 +137,13 @@ export interface ColumnChartConfig extends BaseChartOptions { } export interface AreaChartConfig extends BaseChartOptions { + /** + * The series data for an area chart. + */ series: AreaSeries[]; + /** + * Specifies that this is an area chart. + */ type: "area"; } diff --git a/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts b/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts index 9c10f44de7..e00d3fc229 100644 --- a/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts +++ b/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts @@ -12,7 +12,14 @@ const ChartProviderExample = () => { ] return ( - + ); @@ -77,6 +84,7 @@ const DefaultLineExample = () => { title: { text: "Solar Employment Growth by Sector, 2010-2016", }, + enableCredits: true, }} > @@ -115,6 +123,7 @@ const LineTimeSeriesPanZoomExample = () => { yAxisTitle: { text: "Exchange rate", }, + enableCredits: true, }} > @@ -146,6 +155,7 @@ const DefaultAreaExample = () => { title: { text: "Solar Employment Growth by Sector, 2010-2016", }, + enableCredits: true, }} > @@ -185,6 +195,7 @@ const AreaTimeSeriesPanZoomExample = () => { yAxisTitle: { text: "Exchange rate", }, + enableCredits: true, }} > @@ -220,6 +231,7 @@ const DefaultColumnExample = () => { title: { text: "Fruit popularity", }, + enableCredits: true, }} > @@ -256,6 +268,8 @@ const ColumnStackedNormalExample = () => { text: "Fruit popularity", }, stackingType: "normal", + showDataLabels: true, + enableCredits: true }} > @@ -292,6 +306,7 @@ const ColumnStackedPercentExample = () => { text: "Fruit popularity", }, stackingType: "percent", + enableCredits: true, }} > @@ -329,6 +344,7 @@ const ColumnGroupedAxisExample = () => { text: "Fruit popularity", }, xAxisCategories: ["2020", "2021", "2022", "2023"], + enableCredits: true, }} > diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx index 27965ff22a..1b6f5c592b 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx @@ -112,7 +112,7 @@ export const getStaticProps = async () => { {DefaultColumnExample} -### Stacked - Normal +### Stacked - Normal with Data Labels Date: Fri, 25 Apr 2025 12:59:20 -0500 Subject: [PATCH 36/54] feat(data-visualization): watermark on examples --- .../data-visualization/BaseChart.tsx | 15 +++++++++++++-- .../data-visualization/ChartExamples.ts | 19 ++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx index 82994b5e2c..3b2cc7edae 100644 --- a/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx +++ b/packages/paste-website/src/component-examples/data-visualization/BaseChart.tsx @@ -10,12 +10,23 @@ const Chart: React.FC = () => { applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); const chartRef = React.useRef(null); const { options, setChart, setChartRef } = React.useContext(ChartContext); + const pasteThemedOptions = usePasteHighchartsTheme(options); const [chartOptions, setChartOptions] = React.useState( - Highcharts.merge({ plotOptions: { series: { animation: false } } }, usePasteHighchartsTheme(options)), + Highcharts.merge(pasteThemedOptions, { + // only affects our docs live examples. Want to optimize and show licensing info + plotOptions: { series: { animation: false } }, + credits: { ...pasteThemedOptions.credits, enabled: true }, + }), ); React.useLayoutEffect(() => { - setChartOptions(Highcharts.merge(chartOptions, options)); + setChartOptions( + Highcharts.merge(chartOptions, options, { + // only affects our docs live examples. Want to optimize and show licensing info + plotOptions: { series: { animation: false } }, + credits: { ...pasteThemedOptions.credits, enabled: true }, + }), + ); }, [options]); React.useEffect(() => { diff --git a/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts b/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts index e00d3fc229..95e61ed597 100644 --- a/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts +++ b/packages/paste-website/src/component-examples/data-visualization/ChartExamples.ts @@ -16,9 +16,8 @@ const ChartProviderExample = () => { type: "line", series: lineSeriesData, title: { - text: "Solar Employment Growth by Sector, 2010-2016", + text: "Solar Employment Growth by Sector", }, - enableCredits: true, }}> @@ -82,9 +81,8 @@ const DefaultLineExample = () => { type: "line", series: lineSeriesData, title: { - text: "Solar Employment Growth by Sector, 2010-2016", + text: "Solar Employment Growth by Sector", }, - enableCredits: true, }} > @@ -123,7 +121,6 @@ const LineTimeSeriesPanZoomExample = () => { yAxisTitle: { text: "Exchange rate", }, - enableCredits: true, }} > @@ -153,9 +150,8 @@ const DefaultAreaExample = () => { type: "area", series: areaSeriesData, title: { - text: "Solar Employment Growth by Sector, 2010-2016", + text: "Solar Employment Growth by Sector", }, - enableCredits: true, }} > @@ -166,7 +162,6 @@ const DefaultAreaExample = () => { render(); `.trim(); - export const AreaTimeSeriesPanZoomExample = ` const AreaTimeSeriesPanZoomExample = () => { const exampleDataStructure = [ @@ -195,7 +190,6 @@ const AreaTimeSeriesPanZoomExample = () => { yAxisTitle: { text: "Exchange rate", }, - enableCredits: true, }} > @@ -231,7 +225,6 @@ const DefaultColumnExample = () => { title: { text: "Fruit popularity", }, - enableCredits: true, }} > @@ -269,7 +262,6 @@ const ColumnStackedNormalExample = () => { }, stackingType: "normal", showDataLabels: true, - enableCredits: true }} > @@ -306,7 +298,6 @@ const ColumnStackedPercentExample = () => { text: "Fruit popularity", }, stackingType: "percent", - enableCredits: true, }} > @@ -317,7 +308,6 @@ const ColumnStackedPercentExample = () => { render(); `.trim(); - export const ColumnGroupedAxisExample = ` const ColumnGroupedAxisExample = () => { const columnSeriesData = [ @@ -344,7 +334,6 @@ const ColumnGroupedAxisExample = () => { text: "Fruit popularity", }, xAxisCategories: ["2020", "2021", "2022", "2023"], - enableCredits: true, }} > @@ -353,4 +342,4 @@ const ColumnGroupedAxisExample = () => { }; render(); -`.trim(); \ No newline at end of file +`.trim(); From aa4729011584f9ef6728dd6eca453d6cba3332d9 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Mon, 28 Apr 2025 11:53:17 -0500 Subject: [PATCH 37/54] feat(data-visualization): update chart types content --- .../components/chart-provider/type-docs.json | 18 +++++++++--------- .../pages/components/chart-provider/index.mdx | 8 ++++++++ .../engineering/chart-types.mdx | 6 ------ 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/paste-core/components/chart-provider/type-docs.json b/packages/paste-core/components/chart-provider/type-docs.json index 8c36b0bb7b..7dfb6faeef 100644 --- a/packages/paste-core/components/chart-provider/type-docs.json +++ b/packages/paste-core/components/chart-provider/type-docs.json @@ -1,12 +1,5 @@ { "ChartProvider": { - "highchartsOptions": { - "type": "Options", - "defaultValue": "null", - "required": true, - "externalProp": false, - "description": "Overrides the default element name to apply unique styles with the Customization Provider" - }, "about": { "type": "string", "defaultValue": null, @@ -486,6 +479,13 @@ "required": false, "externalProp": true }, + "highchartsOptions": { + "type": "Options", + "defaultValue": "null", + "required": false, + "externalProp": false, + "description": "Overrides the default element name to apply unique styles with the Customization Provider" + }, "id": { "type": "string", "defaultValue": null, @@ -1574,8 +1574,8 @@ "required": false, "externalProp": true }, - "pasteOptions": { - "type": "never", + "options": { + "type": "ChartTypeOptions", "defaultValue": null, "required": false, "externalProp": false diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index b29d906c1f..ad2579afb5 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -54,6 +54,14 @@ Chart Provider is a wrapper around Highcharts that provides a consistent API for We highly recommend using our [BaseChart](/foundations/data-visualization/engineering#basechart) code inside the ChartProvider to ensure that the chart is rendered correctly and state is correctly stored. +## Usage + +The Chart Provider accepts a single object that defines the chart to render. This can be passed either through the `options` prop for supported Paste charts or through the `highchartsOptions` prop to render custom charts using the full Highcharts API. + +Using our supported chart options gives engineers a more streamlined and intuitive API for building various chart types. We offer a set of base configuration options shared across all charts, along with additional options specific to certain chart types. This approach simplifies the often heavily nested Highcharts API, making it easier to configure charts with clearer and more approachable property names. + +For all chart configuration options you can check our code [here](https://github.com/twilio-labs/paste/tree/main/packages/paste-libraries/data-visualization/src/types.ts) + ## Examples ### Line Chart diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx index 1b6f5c592b..f18f21208d 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx @@ -58,8 +58,6 @@ export const getStaticProps = async () => { ## Line -### Default Line - { ## Area -### Default Area - { ## Column -### Default Column - Date: Tue, 29 Apr 2025 12:30:14 -0500 Subject: [PATCH 38/54] feat(data-visualization): adding typedocs --- .../data-visualization/package.json | 1 + .../data-visualization/src/index.tsx | 12 +- .../data-visualization/src/types.ts | 13 +- .../data-visualization/type-docs.json | 720 ++++++++++++++++++ tools/build/generate-type-docs/index.ts | 8 +- 5 files changed, 744 insertions(+), 10 deletions(-) create mode 100644 packages/paste-libraries/data-visualization/type-docs.json diff --git a/packages/paste-libraries/data-visualization/package.json b/packages/paste-libraries/data-visualization/package.json index f47fc7c2ad..296d80cd55 100644 --- a/packages/paste-libraries/data-visualization/package.json +++ b/packages/paste-libraries/data-visualization/package.json @@ -20,6 +20,7 @@ "scripts": { "build": "yarn clean && NODE_ENV=production node build.js && tsc", "build:js": "NODE_ENV=development node build.js", + "build:typedocs": "tsx ../../../tools/build/generate-type-docs --skipPropsNameRule", "clean": "rm -rf ./dist", "tsc": "tsc" }, diff --git a/packages/paste-libraries/data-visualization/src/index.tsx b/packages/paste-libraries/data-visualization/src/index.tsx index 6e95fef839..fdb808b019 100644 --- a/packages/paste-libraries/data-visualization/src/index.tsx +++ b/packages/paste-libraries/data-visualization/src/index.tsx @@ -1,4 +1,14 @@ export { usePasteHighchartsTheme } from "./usePasteHighchartsTheme"; export { applyPasteHighchartsModules } from "./applyPasteHighchartsModules"; export { transformToHighchartsOptions } from "./transformers"; -export * from "./types"; +export type { + BaseChartOptions, + ChartTypeOptions, + ChartConfig, + AreaChartConfig, + AreaSeries, + ColumnChartConfig, + ColumnSeries, + LineChartConfig, + LineSeries, +} from "./types"; diff --git a/packages/paste-libraries/data-visualization/src/types.ts b/packages/paste-libraries/data-visualization/src/types.ts index 77f5f542a3..64a19d57e6 100644 --- a/packages/paste-libraries/data-visualization/src/types.ts +++ b/packages/paste-libraries/data-visualization/src/types.ts @@ -18,12 +18,9 @@ export type AreaSeries = Pick; +export type ColumnSeries = Pick; -type ChartConfig = Pick; +export type ChartConfig = Pick; type ChartAccessibilityConfig = Pick< Highcharts.AccessibilityOptions, @@ -90,13 +87,13 @@ export interface BaseChartOptions { xAxisTitle?: TitleConfig; /** * Controls the display of teh watermark in the bottom right of the chart accrediting Highcharts. Not needed for projects with a license and disbaled by default. - * + * * @default false */ enableCredits?: boolean; /** * Controls whether the chart is animated. - * + * * @default true */ isAnimated?: boolean; @@ -108,7 +105,7 @@ export interface BaseChartOptions { export interface LineChartConfig extends BaseChartOptions { /** - * The series data for a line chart. + * The series data for a line chart. */ series: LineSeries[]; /** diff --git a/packages/paste-libraries/data-visualization/type-docs.json b/packages/paste-libraries/data-visualization/type-docs.json new file mode 100644 index 0000000000..3a4b31ca48 --- /dev/null +++ b/packages/paste-libraries/data-visualization/type-docs.json @@ -0,0 +1,720 @@ +{ + "BaseChartOptions": { + "type": { + "type": "SupportedCharts", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "The type of chart to render. This will determine what other chart specfic options are available." + }, + "accessibility": { + "type": "ChartAccessibilityConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets global accessiblity options such as formatting the point and series text that is read to users when they focus on elements." + }, + "chart": { + "type": "ChartConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets metadata for the chart such as whether it is animated, the height and width of the chart, and other chart options." + }, + "enableCredits": { + "type": "boolean", + "defaultValue": false, + "required": false, + "externalProp": false, + "description": "Controls the display of teh watermark in the bottom right of the chart accrediting Highcharts. Not needed for projects with a license and disbaled by default." + }, + "isAnimated": { + "type": "boolean", + "defaultValue": true, + "required": false, + "externalProp": false, + "description": "Controls whether the chart is animated." + }, + "isXTimeAxis": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Render the X axis as a datetime." + }, + "panningType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of panning to enable on the chart allowing users to move the region currently zoomed in on.\nThis will determine whether users can pan in the x, y or both axis." + }, + "pointFormatter": { + "type": "(point: Point) => string", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "A function that formats the point text for Highcharts native tooltips." + }, + "showLegend": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Whether to show the native legend provided by Highcharts." + }, + "subtitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the sub title of the chart. Optionall hide the sub title too. The purpose of setting text but hiding the sub title allows the\nsub title to still be included in any chart descritions read by screen readers." + }, + "title": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the title of the chart. Optionall hide the title too. The purpose of setting text but hiding the title allows the\ntitle to still be included in any chart descritions read by screen readers." + }, + "xAxisCategories": { + "type": "string[]", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The data to be displayed on the x axis labels. This is useful when you do not have the x plot data in your series but need to set the tick labels on teh x axis." + }, + "xAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the x axis of the chart. Optionall hide the x axis too. The purpose of setting text but hiding the x axis allows the\nx axis to still be included in any chart descritions read by screen readers." + }, + "yAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the y axis of the chart. Optionall hide the y axis too. The purpose of setting text but hiding the y axis allows the\ny axis to still be included in any chart descritions read by screen readers." + }, + "zoomingType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of zooming to enable on the chart. This will determine whether users can zoom in the x, y or both axis." + } + }, + "ChartTypeOptions": { + "series": { + "type": "LineSeries[] | ColumnSeries[] | AreaSeries[]", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "The series data for a line chart.\n\n\nThe series data for a column chart.\n\n\nThe series data for an area chart." + }, + "type": { + "type": "\"line\" | \"column\" | \"area\"", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "Specifies that this is a line chart.\n\n\nSpecifies that this is a column chart.\n\n\nSpecifies that this is an area chart." + }, + "accessibility": { + "type": "ChartAccessibilityConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets global accessiblity options such as formatting the point and series text that is read to users when they focus on elements." + }, + "chart": { + "type": "ChartConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets metadata for the chart such as whether it is animated, the height and width of the chart, and other chart options." + }, + "enableCredits": { + "type": "boolean", + "defaultValue": false, + "required": false, + "externalProp": false, + "description": "Controls the display of teh watermark in the bottom right of the chart accrediting Highcharts. Not needed for projects with a license and disbaled by default." + }, + "isAnimated": { + "type": "boolean", + "defaultValue": true, + "required": false, + "externalProp": false, + "description": "Controls whether the chart is animated." + }, + "isXTimeAxis": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Render the X axis as a datetime." + }, + "panningType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of panning to enable on the chart allowing users to move the region currently zoomed in on.\nThis will determine whether users can pan in the x, y or both axis." + }, + "pointFormatter": { + "type": "(point: Point) => string", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "A function that formats the point text for Highcharts native tooltips." + }, + "showLegend": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Whether to show the native legend provided by Highcharts." + }, + "subtitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the sub title of the chart. Optionall hide the sub title too. The purpose of setting text but hiding the sub title allows the\nsub title to still be included in any chart descritions read by screen readers." + }, + "title": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the title of the chart. Optionall hide the title too. The purpose of setting text but hiding the title allows the\ntitle to still be included in any chart descritions read by screen readers." + }, + "xAxisCategories": { + "type": "string[]", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The data to be displayed on the x axis labels. This is useful when you do not have the x plot data in your series but need to set the tick labels on teh x axis." + }, + "xAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the x axis of the chart. Optionall hide the x axis too. The purpose of setting text but hiding the x axis allows the\nx axis to still be included in any chart descritions read by screen readers." + }, + "yAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the y axis of the chart. Optionall hide the y axis too. The purpose of setting text but hiding the y axis allows the\ny axis to still be included in any chart descritions read by screen readers." + }, + "zoomingType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of zooming to enable on the chart. This will determine whether users can zoom in the x, y or both axis." + } + }, + "ChartConfig": { + "animation": { + "type": "boolean | Partial", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock, Highmaps, Gantt) Set the overall animation for\nall chart updating. Animation can be disabled throughout the chart by\nsetting it to false here. It can be overridden for each individual API\nmethod as a function parameter. The only animation not affected by this\noption is the initial series animation, see plotOptions.series.animation.\n\nThe animation can either be set as a boolean or a configuration object.\nIf `true`, it will use the 'swing' jQuery easing and a duration of 500\nms. If used as a configuration object, the following properties are\nsupported:\n\n- `defer`: The animation delay time in milliseconds.\n\n- `duration`: The duration of the animation in milliseconds.\n\n- `easing`: A string reference to an easing function set on the `Math`\nobject. See the easing demo.\n\nWhen zooming on a series with less than 100 points, the chart redraw will\nbe done with animation, but in case of more data points, it is necessary\nto set this option to ensure animation on zoom." + }, + "height": { + "type": "string | number", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock, Highmaps, Gantt) An explicit height for the\nchart. If a _number_, the height is given in pixels. If given a\n_percentage string_ (for example `'56%'`), the height is given as the\npercentage of the actual chart width. This allows for preserving the\naspect ratio across responsive sizes.\n\nBy default (when `null`) the height is calculated from the offset height\nof the containing element, or 400 pixels if the containing element's\nheight is 0." + }, + "width": { + "type": "string | number", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock, Highmaps, Gantt) An explicit width for the chart.\nBy default (when `null`) the width is calculated from the offset width of\nthe containing element." + } + }, + "AreaChartConfig": { + "series": { + "type": "AreaSeries[]", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "The series data for an area chart." + }, + "type": { + "type": "\"area\"", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "Specifies that this is an area chart." + }, + "accessibility": { + "type": "ChartAccessibilityConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets global accessiblity options such as formatting the point and series text that is read to users when they focus on elements." + }, + "chart": { + "type": "ChartConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets metadata for the chart such as whether it is animated, the height and width of the chart, and other chart options." + }, + "enableCredits": { + "type": "boolean", + "defaultValue": false, + "required": false, + "externalProp": false, + "description": "Controls the display of teh watermark in the bottom right of the chart accrediting Highcharts. Not needed for projects with a license and disbaled by default." + }, + "isAnimated": { + "type": "boolean", + "defaultValue": true, + "required": false, + "externalProp": false, + "description": "Controls whether the chart is animated." + }, + "isXTimeAxis": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Render the X axis as a datetime." + }, + "panningType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of panning to enable on the chart allowing users to move the region currently zoomed in on.\nThis will determine whether users can pan in the x, y or both axis." + }, + "pointFormatter": { + "type": "(point: Point) => string", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "A function that formats the point text for Highcharts native tooltips." + }, + "showLegend": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Whether to show the native legend provided by Highcharts." + }, + "subtitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the sub title of the chart. Optionall hide the sub title too. The purpose of setting text but hiding the sub title allows the\nsub title to still be included in any chart descritions read by screen readers." + }, + "title": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the title of the chart. Optionall hide the title too. The purpose of setting text but hiding the title allows the\ntitle to still be included in any chart descritions read by screen readers." + }, + "xAxisCategories": { + "type": "string[]", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The data to be displayed on the x axis labels. This is useful when you do not have the x plot data in your series but need to set the tick labels on teh x axis." + }, + "xAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the x axis of the chart. Optionall hide the x axis too. The purpose of setting text but hiding the x axis allows the\nx axis to still be included in any chart descritions read by screen readers." + }, + "yAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the y axis of the chart. Optionall hide the y axis too. The purpose of setting text but hiding the y axis allows the\ny axis to still be included in any chart descritions read by screen readers." + }, + "zoomingType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of zooming to enable on the chart. This will determine whether users can zoom in the x, y or both axis." + } + }, + "AreaSeries": { + "accessibility": { + "type": "SeriesAccessibilityOptionsObject", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) Accessibility options for a series." + }, + "color": { + "type": "string | GradientColorObject | PatternObject", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) The main color of the series. In line type series\nit applies to the line and the point markers unless otherwise specified.\nIn bar type series it applies to the bars unless a color is specified per\npoint. The default value is pulled from the `options.colors` array.\n\nIn styled mode, the color can be defined by the colorIndex option. Also,\nthe series color can be set with the `.highcharts-series`,\n`.highcharts-color-{n}`, `.highcharts-{type}-series` or\n`.highcharts-series-{n}` class, or individual classes given by the\n`className` option." + }, + "data": { + "type": "(\n | number\n | [string | number, number | null]\n | PointOptionsObject\n | null\n)[]", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) An array of data points for the series. For the\n`area` series type, points can be given in the following ways:\n\n1. An array of numerical values. In this case, the numerical values will\nbe interpreted as `y` options. The `x` values will be automatically\ncalculated, either starting at 0 and incremented by 1, or from\n`pointStart` * and `pointInterval` given in the series options. If the\naxis has categories, these will be used. Example: (see online\ndocumentation for example)\n\n2. An array of arrays with 2 values. In this case, the values correspond\nto `x,y`. If the first value is a string, it is applied as the name of\nthe point, and the `x` value is inferred. (see online documentation for\nexample)\n\n3. An array of objects with named values. The following snippet shows\nonly a few settings, see the complete options set below. If the total\nnumber of data points exceeds the series' turboThreshold, this option is\nnot available. (see online documentation for example)" + }, + "name": { + "type": "string", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock, Highmaps, Gantt) The name of the series as shown\nin the legend, tooltip etc." + } + }, + "ColumnChartConfig": { + "series": { + "type": "ColumnSeries[]", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "The series data for a column chart." + }, + "type": { + "type": "\"column\"", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "Specifies that this is a column chart." + }, + "accessibility": { + "type": "ChartAccessibilityConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets global accessiblity options such as formatting the point and series text that is read to users when they focus on elements." + }, + "chart": { + "type": "ChartConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets metadata for the chart such as whether it is animated, the height and width of the chart, and other chart options." + }, + "enableCredits": { + "type": "boolean", + "defaultValue": false, + "required": false, + "externalProp": false, + "description": "Controls the display of teh watermark in the bottom right of the chart accrediting Highcharts. Not needed for projects with a license and disbaled by default." + }, + "isAnimated": { + "type": "boolean", + "defaultValue": true, + "required": false, + "externalProp": false, + "description": "Controls whether the chart is animated." + }, + "isXTimeAxis": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Render the X axis as a datetime." + }, + "panningType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of panning to enable on the chart allowing users to move the region currently zoomed in on.\nThis will determine whether users can pan in the x, y or both axis." + }, + "pointFormatter": { + "type": "(point: Point) => string", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "A function that formats the point text for Highcharts native tooltips." + }, + "showDataLabels": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Show the number value for the column on top of the section. Works for regular and stacked variants." + }, + "showLegend": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Whether to show the native legend provided by Highcharts." + }, + "stackingType": { + "type": "\"normal\" | \"percent\"", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of stacking to use for the column chart, whether to show percentage stacked or normal." + }, + "subtitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the sub title of the chart. Optionall hide the sub title too. The purpose of setting text but hiding the sub title allows the\nsub title to still be included in any chart descritions read by screen readers." + }, + "title": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the title of the chart. Optionall hide the title too. The purpose of setting text but hiding the title allows the\ntitle to still be included in any chart descritions read by screen readers." + }, + "xAxisCategories": { + "type": "string[]", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The data to be displayed on the x axis labels. This is useful when you do not have the x plot data in your series but need to set the tick labels on teh x axis." + }, + "xAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the x axis of the chart. Optionall hide the x axis too. The purpose of setting text but hiding the x axis allows the\nx axis to still be included in any chart descritions read by screen readers." + }, + "yAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the y axis of the chart. Optionall hide the y axis too. The purpose of setting text but hiding the y axis allows the\ny axis to still be included in any chart descritions read by screen readers." + }, + "zoomingType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of zooming to enable on the chart. This will determine whether users can zoom in the x, y or both axis." + } + }, + "ColumnSeries": { + "accessibility": { + "type": "SeriesAccessibilityOptionsObject", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) Accessibility options for a series." + }, + "color": { + "type": "string | GradientColorObject | PatternObject", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) The main color of the series. In line type series\nit applies to the line and the point markers unless otherwise specified.\nIn bar type series it applies to the bars unless a color is specified per\npoint. The default value is pulled from the `options.colors` array.\n\nIn styled mode, the color can be defined by the colorIndex option. Also,\nthe series color can be set with the `.highcharts-series`,\n`.highcharts-color-{n}`, `.highcharts-{type}-series` or\n`.highcharts-series-{n}` class, or individual classes given by the\n`className` option." + }, + "data": { + "type": "(\n | number\n | [string | number, number | null]\n | PointOptionsObject\n | null\n)[]", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) An array of data points for the series. For the\n`column` series type, points can be given in the following ways:\n\n1. An array of numerical values. In this case, the numerical values will\nbe interpreted as `y` options. The `x` values will be automatically\ncalculated, either starting at 0 and incremented by 1, or from\n`pointStart` and `pointInterval` given in the series options. If the axis\nhas categories, these will be used. Example: (see online documentation\nfor example)\n\n2. An array of arrays with 2 values. In this case, the values correspond\nto `x,y`. If the first value is a string, it is applied as the name of\nthe point, and the `x` value is inferred. (see online documentation for\nexample)\n\n3. An array of objects with named values. The following snippet shows\nonly a few settings, see the complete options set below. If the total\nnumber of data points exceeds the series' turboThreshold, this option is\nnot available. (see online documentation for example)" + }, + "events": { + "type": "SeriesEventsOptionsObject", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) General event handlers for the series items.\nThese event hooks can also be attached to the series at run time using\nthe `Highcharts.addEvent` function." + }, + "name": { + "type": "string", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock, Highmaps, Gantt) The name of the series as shown\nin the legend, tooltip etc." + } + }, + "LineChartConfig": { + "series": { + "type": "LineSeries[]", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "The series data for a line chart." + }, + "type": { + "type": "\"line\"", + "defaultValue": null, + "required": true, + "externalProp": false, + "description": "Specifies that this is a line chart." + }, + "accessibility": { + "type": "ChartAccessibilityConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets global accessiblity options such as formatting the point and series text that is read to users when they focus on elements." + }, + "chart": { + "type": "ChartConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Sets metadata for the chart such as whether it is animated, the height and width of the chart, and other chart options." + }, + "enableCredits": { + "type": "boolean", + "defaultValue": false, + "required": false, + "externalProp": false, + "description": "Controls the display of teh watermark in the bottom right of the chart accrediting Highcharts. Not needed for projects with a license and disbaled by default." + }, + "isAnimated": { + "type": "boolean", + "defaultValue": true, + "required": false, + "externalProp": false, + "description": "Controls whether the chart is animated." + }, + "isXTimeAxis": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Render the X axis as a datetime." + }, + "panningType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of panning to enable on the chart allowing users to move the region currently zoomed in on.\nThis will determine whether users can pan in the x, y or both axis." + }, + "pointFormatter": { + "type": "(point: Point) => string", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "A function that formats the point text for Highcharts native tooltips." + }, + "showLegend": { + "type": "boolean", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Whether to show the native legend provided by Highcharts." + }, + "subtitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the sub title of the chart. Optionall hide the sub title too. The purpose of setting text but hiding the sub title allows the\nsub title to still be included in any chart descritions read by screen readers." + }, + "title": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the title of the chart. Optionall hide the title too. The purpose of setting text but hiding the title allows the\ntitle to still be included in any chart descritions read by screen readers." + }, + "xAxisCategories": { + "type": "string[]", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The data to be displayed on the x axis labels. This is useful when you do not have the x plot data in your series but need to set the tick labels on teh x axis." + }, + "xAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the x axis of the chart. Optionall hide the x axis too. The purpose of setting text but hiding the x axis allows the\nx axis to still be included in any chart descritions read by screen readers." + }, + "yAxisTitle": { + "type": "TitleConfig", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "Configure the y axis of the chart. Optionall hide the y axis too. The purpose of setting text but hiding the y axis allows the\ny axis to still be included in any chart descritions read by screen readers." + }, + "zoomingType": { + "type": "OptionsZoomTypeValue", + "defaultValue": null, + "required": false, + "externalProp": false, + "description": "The type of zooming to enable on the chart. This will determine whether users can zoom in the x, y or both axis." + } + }, + "LineSeries": { + "accessibility": { + "type": "SeriesAccessibilityOptionsObject", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) Accessibility options for a series." + }, + "color": { + "type": "string | GradientColorObject | PatternObject", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) The main color of the series. In line type series\nit applies to the line and the point markers unless otherwise specified.\nIn bar type series it applies to the bars unless a color is specified per\npoint. The default value is pulled from the `options.colors` array.\n\nIn styled mode, the color can be defined by the colorIndex option. Also,\nthe series color can be set with the `.highcharts-series`,\n`.highcharts-color-{n}`, `.highcharts-{type}-series` or\n`.highcharts-series-{n}` class, or individual classes given by the\n`className` option." + }, + "dashStyle": { + "type": "DashStyleValue", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) Name of the dash style to use for the graph, or\nfor some series types the outline of each shape.\n\nIn styled mode, the stroke dash-array can be set with the same classes as\nlisted under series.color." + }, + "data": { + "type": "(\n | number\n | [string | number, number | null]\n | PointOptionsObject\n | null\n)[]", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) An array of data points for the series. For the\n`line` series type, points can be given in the following ways:\n\n1. An array of numerical values. In this case, the numerical values will\nbe interpreted as `y` options. The `x` values will be automatically\ncalculated, either starting at 0 and incremented by 1, or from\n`pointStart` and `pointInterval` given in the series options. If the axis\nhas categories, these will be used. Example: (see online documentation\nfor example)\n\n2. An array of arrays with 2 values. In this case, the values correspond\nto `x,y`. If the first value is a string, it is applied as the name of\nthe point, and the `x` value is inferred. (see online documentation for\nexample)\n\n3. An array of objects with named values. The following snippet shows\nonly a few settings, see the complete options set below. If the total\nnumber of data points exceeds the series' turboThreshold, this option is\nnot available. (see online documentation for example)\n\n**Note:** In TypeScript you have to extend `PointOptionsObject` with an\nadditional declaration to allow custom data types: ```ts declare module\n`highcharts` { interface PointOptionsObject { custom: Record; } } ```" + }, + "lineWidth": { + "type": "number", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) Pixel width of the graph line." + }, + "marker": { + "type": "PointMarkerOptionsObject", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock) Options for the point markers of line-like\nseries. Properties like `fillColor`, `lineColor` and `lineWidth` define\nthe visual appearance of the markers. Other series types, like column\nseries, don't have markers, but have visual options on the series level\ninstead.\n\nIn styled mode, the markers can be styled with the `.highcharts-point`,\n`.highcharts-point-hover` and `.highcharts-point-select` class names." + }, + "name": { + "type": "string", + "defaultValue": null, + "required": false, + "externalProp": true, + "description": "(Highcharts, Highstock, Highmaps, Gantt) The name of the series as shown\nin the legend, tooltip etc." + } + } +} diff --git a/tools/build/generate-type-docs/index.ts b/tools/build/generate-type-docs/index.ts index ea0c4f81d4..0d6f517f9c 100644 --- a/tools/build/generate-type-docs/index.ts +++ b/tools/build/generate-type-docs/index.ts @@ -84,10 +84,16 @@ function extractPropertiesOfTypeName( let typeName = (typeStatement as any).name.getText() as string; + // Doesn't pick up the data visualization types of they don't end in props. They are not component props so making an exception we can reuse. + const skipPropFiltering = process.argv.find((arg => arg === "--skipPropsNameRule")); + if (typeName.endsWith("Props")) { typeName = typeName.replace(/Props$/, ""); results[typeName] = sortByRequiredProperties(properties); - } else { + } else if(skipPropFiltering){ + results[typeName] = sortByRequiredProperties(properties); + } + else { log("Omitting type", `\`${typeName}\``); } } From ff5cf146124c4a127bf62bce7ee4a899d8ae6d8c Mon Sep 17 00:00:00 2001 From: krisantrobus <55083528+krisantrobus@users.noreply.github.com> Date: Tue, 29 Apr 2025 12:30:37 -0500 Subject: [PATCH 39/54] Update packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx Co-authored-by: Sarah --- .../src/components/site-wrapper/sidebar/SidebarNavigation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index 5a2b416715..a4fe061850 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -138,7 +138,7 @@ const SiteSidebarNavigation = (): JSX.Element => { Overview Overview From 1609a2be355b18681aa84f3cc3a52ad079535625 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 29 Apr 2025 12:31:06 -0500 Subject: [PATCH 40/54] feat(data-visualization): chart option docs --- .../src/components/DataVizPropsTables.tsx | 196 ++++++++++++++++++ .../src/components/PropsTables.tsx | 1 + .../sidebar/SidebarNavigation.tsx | 3 + .../engineering/chart-options.mdx | 59 ++++++ .../engineering/chart-types.mdx | 3 +- 5 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 packages/paste-website/src/components/DataVizPropsTables.tsx create mode 100644 packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-options.mdx diff --git a/packages/paste-website/src/components/DataVizPropsTables.tsx b/packages/paste-website/src/components/DataVizPropsTables.tsx new file mode 100644 index 0000000000..a18d859890 --- /dev/null +++ b/packages/paste-website/src/components/DataVizPropsTables.tsx @@ -0,0 +1,196 @@ +import { Box } from "@twilio-paste/box"; +import { Disclosure, DisclosureContent, DisclosureHeading } from "@twilio-paste/disclosure"; +import { InlineCode } from "@twilio-paste/inline-code"; +import { RequiredDot } from "@twilio-paste/label"; +import { Paragraph } from "@twilio-paste/paragraph"; +import { Text } from "@twilio-paste/text"; +import Markdown from "markdown-to-jsx"; +import * as React from "react"; + +import { + type ComponentApiProp, + type ComponentApiPropDetails, + type GroupedComponentApi, +} from "../utils/componentApiUtils"; +import { AnchoredHeading } from "./Heading"; + +export interface PropsTableProps { + componentApi: GroupedComponentApi; +} +export interface PropsListProps { + props: ComponentApiProp; +} +export interface PropPairProps { + term: React.ReactNode; + description: React.ReactNode; +} +export interface PropTypeProps { + children: NonNullable; +} + +const MarkdownConverter: React.FC<{ description: string }> = ({ description }) => { + return ( + + {description} + + ); +}; + +const PropType: React.FC> = ({ children }) => { + return ( + + {children} + + ); +}; +PropType.displayName = "PropType"; + +const PropPair: React.FC = ({ term, description }) => { + return ( + + + {term} + + + {description} + + + ); +}; +PropPair.displayName = "PropPair"; + +const PropsList: React.FC = ({ props }) => { + return ( + + {Object.keys(props).map((propName) => { + const prop: ComponentApiPropDetails = props[propName]; + return ( + + + + + {propName} + {" "} + {prop.required ? ( + + + + Required + + + ) : ( + "" + )} + + {prop.description && ( + + + + )} + + + {prop.type}} /> + {prop.defaultValue && prop.defaultValue !== " " ? ( + {prop.defaultValue}} /> + ) : null} + + + ); + })} + + ); +}; +PropsList.displayName = "PropsList"; + +const DataVizPropsTables: React.FC = ({ componentApi }) => { + const propsTable = React.useMemo(() => componentApi, [componentApi]); + const baseChartOptions = Object.keys(propsTable.BaseChartOptions.internalProps); + + return ( + <> + {Object.keys(propsTable).map((componentName) => { + const { internalProps, externalProps } = propsTable[componentName]; + const isChartConfig = componentName.includes("ChartConfig"); + console.log(internalProps); + /** + * filter internalProps to remove baseChartOptions and put them under inherited so consumers can see the options + * that only apply to the chart type + **/ + const getNonBaseChartOptions = () => { + return Object.keys(internalProps).reduce((acc: ComponentApiProp, propName: string) => { + if (!baseChartOptions.includes(propName)) { + acc[propName] = internalProps[propName]; + } + return acc; + }, {}); + }; + + return ( + + + {componentName} + + {internalProps && } + {(isChartConfig || externalProps) && ( + + + Inherited props + + + + Paste components will often extend native HTML elements and as a result will inherit or extend their + available properties. Below is a list of the props this component has inherited and are also + available to use. + + + + + )} + + ); + })} + + ); +}; + +DataVizPropsTables.displayName = "DataVizPropsTables"; + +export { DataVizPropsTables }; diff --git a/packages/paste-website/src/components/PropsTables.tsx b/packages/paste-website/src/components/PropsTables.tsx index 4fd2bff7fd..c4074a5ad7 100644 --- a/packages/paste-website/src/components/PropsTables.tsx +++ b/packages/paste-website/src/components/PropsTables.tsx @@ -164,6 +164,7 @@ const PropsTable: React.FC = ({ componentApi }) => { available properties. Below is a list of the props this component has inherited and are also available to use. + {JSON.stringify(externalProps, null, 2)} diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index 5a2b416715..36c8703d09 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -145,6 +145,9 @@ const SiteSidebarNavigation = (): JSX.Element => { Chart types + + Chart options + { + const navigationData = await getNavigationData(); + const {componentApi, componentApiTocData} = getComponentApi('@twilio-paste/data-visualization-library'); + + return { + props: { + navigationData, + componentApi, + componentApiTocData + } + }; +}; + + + + + + + + + + + + + +## Props + + + + + diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx index f18f21208d..b8a0ee739a 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx @@ -1,5 +1,5 @@ export const meta = { - title: "Data Visualization", + title: "Data Types", description: "Display the supported chart types for the Paste Data Visualization library with coded examples.", slug: "/foundations/data-visualization/engineering/chart-types", }; @@ -30,6 +30,7 @@ export default DefaultLayout; export const getStaticProps = async () => { const navigationData = await getNavigationData(); + return { props: { navigationData, From f878f40e739595d479d4508c93cc3b2655ebf32e Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 29 Apr 2025 13:22:08 -0500 Subject: [PATCH 41/54] feat(data-visualization): cleanup chart options --- .../src/components/PropsTables.tsx | 1 - .../sidebar/SidebarNavigation.tsx | 3 - .../pages/components/chart-provider/api.mdx | 34 ++++++++++- .../pages/components/chart-provider/index.mdx | 6 +- .../engineering/chart-options.mdx | 59 ------------------- 5 files changed, 36 insertions(+), 67 deletions(-) delete mode 100644 packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-options.mdx diff --git a/packages/paste-website/src/components/PropsTables.tsx b/packages/paste-website/src/components/PropsTables.tsx index c4074a5ad7..4fd2bff7fd 100644 --- a/packages/paste-website/src/components/PropsTables.tsx +++ b/packages/paste-website/src/components/PropsTables.tsx @@ -164,7 +164,6 @@ const PropsTable: React.FC = ({ componentApi }) => { available properties. Below is a list of the props this component has inherited and are also available to use. - {JSON.stringify(externalProps, null, 2)} diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index 36c8703d09..5a2b416715 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -145,9 +145,6 @@ const SiteSidebarNavigation = (): JSX.Element => { Chart types - - Chart options - { const navigationData = await getNavigationData(); const feature = await getFeature('Chart Provider'); const {componentApi, componentApiTocData} = getComponentApi('@twilio-paste/chart-provider'); + const {componentApi: dataVizTypes, componentApiTocData: dataVizApiToDoc } = getComponentApi('@twilio-paste/data-visualization-library'); + const baseChartOptions = Object.keys(dataVizTypes["BaseChartOptions"]["internalProps"]); + /** + * Reformatting the types for data visualization so props for chart tpye configs that inherit form base config is under inherited so users + * can see the configurations that are only affecting that specific chart + */ + Object.keys(dataVizTypes).forEach(typeName => { + if (typeName.includes("ChartConfig")) { + dataVizTypes[typeName].internalProps = Object.keys(dataVizTypes[typeName].internalProps).reduce((acc, propName) => { + if (!baseChartOptions.includes(propName)) { + acc[propName] = dataVizTypes[typeName].internalProps[propName]; + } + return acc; + }, {}); + dataVizTypes[typeName].externalProps = dataVizTypes["BaseChartOptions"]["internalProps"]; + } + }); return { props: { data: { @@ -25,13 +44,14 @@ export const getStaticProps = async () => { ...feature, }, componentApi, - mdxHeadings: [...mdxHeadings, ...componentApiTocData], + mdxHeadings: [...mdxHeadings, ...componentApiTocData, ...dataVizApiToDoc], navigationData, pageHeaderData: { categoryRoute: SidebarCategoryRoutes.COMPONENTS, githubUrl: 'https://github.com/twilio-labs/paste/tree/main/packages/paste-core/components/chart-provider', storybookUrl: '/?path=/story/components-chartprovider', }, + dataVizTypes, }, }; }; @@ -59,3 +79,15 @@ const ChartProviderExample = () => { ## Props + + + + + +The props below are used to configure supported chart types and can be imported from `@twilio-paste/data-visualization-library`. These are used to construct the chart options, ensuring type safety before providing them to the Chart Provider component. + +```javascript +import { LineChartConfig } from '@twilio-paste/data-visualization-library'; +``` + + diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index ad2579afb5..43befeaaa2 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -66,7 +66,7 @@ For all chart configuration options you can check our code [here](https://github ### Line Chart -Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/engineering/chart-types#line). +Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/engineering/chart-types#line). To view the options available to configure this chart, refernce the [API](/components/chart-provider/api#linechartconfig). { - const navigationData = await getNavigationData(); - const {componentApi, componentApiTocData} = getComponentApi('@twilio-paste/data-visualization-library'); - - return { - props: { - navigationData, - componentApi, - componentApiTocData - } - }; -}; - - - - - - - - - - - - - -## Props - - - - - From 80bbe936da7d4d1dde743d54fdecec2f3538122b Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 29 Apr 2025 13:26:10 -0500 Subject: [PATCH 42/54] feat(data-visualization): vrt --- cypress/integration/sitemap-vrt/constants.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cypress/integration/sitemap-vrt/constants.ts b/cypress/integration/sitemap-vrt/constants.ts index 2f1be9121f..0d4bed9e0a 100644 --- a/cypress/integration/sitemap-vrt/constants.ts +++ b/cypress/integration/sitemap-vrt/constants.ts @@ -63,6 +63,8 @@ export const SITEMAP = [ "/components/card/api", "/components/card/changelog", "/components/chart-provider/", + "/components/chart-provider/api", + "/components/chart-provider/changelog", "/components/chat-composer/", "/components/chat-composer/api", "/components/chat-composer/changelog", From 835ff2ef69102abdc49bba3b0eace0b83179f1c3 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 29 Apr 2025 13:45:13 -0500 Subject: [PATCH 43/54] feat(data-visualization): pr cleanup --- .../src/components/DataVizPropsTables.tsx | 196 ------------------ yarn.lock | 1 + 2 files changed, 1 insertion(+), 196 deletions(-) delete mode 100644 packages/paste-website/src/components/DataVizPropsTables.tsx diff --git a/packages/paste-website/src/components/DataVizPropsTables.tsx b/packages/paste-website/src/components/DataVizPropsTables.tsx deleted file mode 100644 index a18d859890..0000000000 --- a/packages/paste-website/src/components/DataVizPropsTables.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import { Box } from "@twilio-paste/box"; -import { Disclosure, DisclosureContent, DisclosureHeading } from "@twilio-paste/disclosure"; -import { InlineCode } from "@twilio-paste/inline-code"; -import { RequiredDot } from "@twilio-paste/label"; -import { Paragraph } from "@twilio-paste/paragraph"; -import { Text } from "@twilio-paste/text"; -import Markdown from "markdown-to-jsx"; -import * as React from "react"; - -import { - type ComponentApiProp, - type ComponentApiPropDetails, - type GroupedComponentApi, -} from "../utils/componentApiUtils"; -import { AnchoredHeading } from "./Heading"; - -export interface PropsTableProps { - componentApi: GroupedComponentApi; -} -export interface PropsListProps { - props: ComponentApiProp; -} -export interface PropPairProps { - term: React.ReactNode; - description: React.ReactNode; -} -export interface PropTypeProps { - children: NonNullable; -} - -const MarkdownConverter: React.FC<{ description: string }> = ({ description }) => { - return ( - - {description} - - ); -}; - -const PropType: React.FC> = ({ children }) => { - return ( - - {children} - - ); -}; -PropType.displayName = "PropType"; - -const PropPair: React.FC = ({ term, description }) => { - return ( - - - {term} - - - {description} - - - ); -}; -PropPair.displayName = "PropPair"; - -const PropsList: React.FC = ({ props }) => { - return ( - - {Object.keys(props).map((propName) => { - const prop: ComponentApiPropDetails = props[propName]; - return ( - - - - - {propName} - {" "} - {prop.required ? ( - - - - Required - - - ) : ( - "" - )} - - {prop.description && ( - - - - )} - - - {prop.type}} /> - {prop.defaultValue && prop.defaultValue !== " " ? ( - {prop.defaultValue}} /> - ) : null} - - - ); - })} - - ); -}; -PropsList.displayName = "PropsList"; - -const DataVizPropsTables: React.FC = ({ componentApi }) => { - const propsTable = React.useMemo(() => componentApi, [componentApi]); - const baseChartOptions = Object.keys(propsTable.BaseChartOptions.internalProps); - - return ( - <> - {Object.keys(propsTable).map((componentName) => { - const { internalProps, externalProps } = propsTable[componentName]; - const isChartConfig = componentName.includes("ChartConfig"); - console.log(internalProps); - /** - * filter internalProps to remove baseChartOptions and put them under inherited so consumers can see the options - * that only apply to the chart type - **/ - const getNonBaseChartOptions = () => { - return Object.keys(internalProps).reduce((acc: ComponentApiProp, propName: string) => { - if (!baseChartOptions.includes(propName)) { - acc[propName] = internalProps[propName]; - } - return acc; - }, {}); - }; - - return ( - - - {componentName} - - {internalProps && } - {(isChartConfig || externalProps) && ( - - - Inherited props - - - - Paste components will often extend native HTML elements and as a result will inherit or extend their - available properties. Below is a list of the props this component has inherited and are also - available to use. - - - - - )} - - ); - })} - - ); -}; - -DataVizPropsTables.displayName = "DataVizPropsTables"; - -export { DataVizPropsTables }; diff --git a/yarn.lock b/yarn.lock index a0eeb9fab6..59402d861a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11513,6 +11513,7 @@ __metadata: "@twilio-paste/box": ^11.0.1 "@twilio-paste/color-contrast-utils": ^5.0.0 "@twilio-paste/customization": ^9.0.1 + "@twilio-paste/data-visualization-library": ^6.0.1 "@twilio-paste/design-tokens": ^10.13.0 "@twilio-paste/style-props": ^10.0.1 "@twilio-paste/styling-library": ^4.0.1 From 65066c561ccbbb4570cea47d696057eea518d796 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 29 Apr 2025 13:46:36 -0500 Subject: [PATCH 44/54] chore(typos): fix various typos --- packages/paste-core/components/tooltip/src/Tooltip.tsx | 2 +- .../src/pages/components/chart-provider/index.mdx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/paste-core/components/tooltip/src/Tooltip.tsx b/packages/paste-core/components/tooltip/src/Tooltip.tsx index 09efee3a91..c50b7cf08a 100644 --- a/packages/paste-core/components/tooltip/src/Tooltip.tsx +++ b/packages/paste-core/components/tooltip/src/Tooltip.tsx @@ -107,7 +107,7 @@ const Tooltip = React.forwardRef( {React.Children.only( // eslint-disable-next-line @typescript-eslint/no-explicit-any - {/* Cannot find type refernce for props in lib */} + {/* Cannot find type references for props in lib */} {(referenceProps: any) => React.cloneElement(children, referenceProps)} , )} diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 43befeaaa2..6367607872 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -66,7 +66,7 @@ For all chart configuration options you can check our code [here](https://github ### Line Chart -Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/engineering/chart-types#line). To view the options available to configure this chart, refernce the [API](/components/chart-provider/api#linechartconfig). +Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/engineering/chart-types#line). To view the options available to configure this chart, references the [API](/components/chart-provider/api#linechartconfig). {DefaultColumnExample} From 369105bbaa77bca800e455721e49634d3ef0cbca Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 29 Apr 2025 13:47:38 -0500 Subject: [PATCH 45/54] chore(typos): revert fix --- packages/paste-core/components/tooltip/src/Tooltip.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/paste-core/components/tooltip/src/Tooltip.tsx b/packages/paste-core/components/tooltip/src/Tooltip.tsx index c50b7cf08a..09efee3a91 100644 --- a/packages/paste-core/components/tooltip/src/Tooltip.tsx +++ b/packages/paste-core/components/tooltip/src/Tooltip.tsx @@ -107,7 +107,7 @@ const Tooltip = React.forwardRef( {React.Children.only( // eslint-disable-next-line @typescript-eslint/no-explicit-any - {/* Cannot find type references for props in lib */} + {/* Cannot find type refernce for props in lib */} {(referenceProps: any) => React.cloneElement(children, referenceProps)} , )} From 069f892cfe97c7f7d3a489230746bb9bf1049186 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Tue, 29 Apr 2025 14:46:34 -0500 Subject: [PATCH 46/54] chore(tests): add support for same title sidebar disclousres --- cypress/integration/sidebar-navigation/index.spec.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cypress/integration/sidebar-navigation/index.spec.ts b/cypress/integration/sidebar-navigation/index.spec.ts index 55f3d365d9..610a1e4c50 100644 --- a/cypress/integration/sidebar-navigation/index.spec.ts +++ b/cypress/integration/sidebar-navigation/index.spec.ts @@ -1,9 +1,10 @@ const sidebarNavigationDisclosures = [ "introduction", + "foundations", + "data-visualization", "for-designers", "for-engineers", "contributing", - "foundations", "content", "patterns", "components", @@ -34,9 +35,10 @@ describe("Sidebar navigation", () => { cy.get(`[data-cy="${contentSelector}"]`).as("currentContent"); cy.get("@currentContent").should("have.css", "display", "none"); cy.get("@currentContent").should("have.attr", "hidden", "hidden"); - - cy.get(`[data-cy="${buttonSelector}"]`).click().should("have.attr", "aria-expanded", "true"); - cy.get("@currentContent").scrollIntoView().should("have.css", "display", "block"); + cy.get(`[data-cy="${buttonSelector}"]`).click({ multiple: true }).should("have.attr", "aria-expanded", "true"); + cy.get("@currentContent").each(($el) => { + cy.wrap($el).scrollIntoView().should("have.css", "display", "block"); + }); }); }); @@ -44,7 +46,7 @@ describe("Sidebar navigation", () => { const buttonSelector = `${BASE}-button-${disclosureName}`; it(`should close the the "${disclosureName}" sidebar disclosure`, () => { - cy.get(`[data-cy="${buttonSelector}"]`).click().should("have.attr", "aria-expanded", "false"); + cy.get(`[data-cy="${buttonSelector}"]`).click({ multiple: true }).should("have.attr", "aria-expanded", "false"); }); }); }); From ab7de863847508293790bfd59aff37fad875dab8 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 30 Apr 2025 09:48:51 -0500 Subject: [PATCH 47/54] feat(data-viz): update docs urls and release versioning --- .changeset/cuddly-berries-explain.md | 4 ++-- cypress/integration/sitemap-vrt/constants.ts | 4 ++-- .../components/site-wrapper/sidebar/SidebarNavigation.tsx | 6 +++--- .../src/pages/components/chart-provider/index.mdx | 2 +- .../{engineering => for-engineers}/chart-types.mdx | 3 ++- .../{engineering => for-engineers}/index.mdx | 3 ++- .../src/pages/foundations/data-visualization/index.mdx | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) rename packages/paste-website/src/pages/foundations/data-visualization/{engineering => for-engineers}/chart-types.mdx (88%) rename packages/paste-website/src/pages/foundations/data-visualization/{engineering => for-engineers}/index.mdx (96%) diff --git a/.changeset/cuddly-berries-explain.md b/.changeset/cuddly-berries-explain.md index ecfe88f3d1..7fafb32120 100644 --- a/.changeset/cuddly-berries-explain.md +++ b/.changeset/cuddly-berries-explain.md @@ -1,6 +1,6 @@ --- -"@twilio-paste/core": minor -"@twilio-paste/data-visualization-library": minor +"@twilio-paste/core": patch +"@twilio-paste/data-visualization-library": patch --- [Data Visualization Library] update Highcharts native tooltip styles to align more closely with Paste styles including correctly setting the font family diff --git a/cypress/integration/sitemap-vrt/constants.ts b/cypress/integration/sitemap-vrt/constants.ts index 0d4bed9e0a..503efdb488 100644 --- a/cypress/integration/sitemap-vrt/constants.ts +++ b/cypress/integration/sitemap-vrt/constants.ts @@ -288,8 +288,8 @@ export const SITEMAP = [ "/foundations/content/word-list/", "/foundations/illustrations/", "/foundations/data-visualization/", - "/foundations/data-visualization/engineering/", - "/foundations/data-visualization/engineering/chart-types/", + "/foundations/data-visualization/for-engineers/", + "/foundations/data-visualization/for-engineers/chart-types/", "/foundations/spacing-and-layout/", "/foundations/typography/", "/inclusive-design/", diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index a4fe061850..edd93a3fc0 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -139,10 +139,10 @@ const SiteSidebarNavigation = (): JSX.Element => { Overview - Overview - + Overview + Chart types diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 54d1a57572..3a4df7fcc9 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -52,7 +52,7 @@ export const getStaticProps = async () => { Chart Provider is a wrapper around Highcharts that provides a consistent API for configuring an individual chart instance. This component has no visible elements and is an engineering asset only. It acts as a store for chart options and provides a context for managing chart state. -We highly recommend using our [BaseChart](/foundations/data-visualization/engineering#basechart) code inside the ChartProvider to ensure that the chart is rendered correctly and state is correctly stored. +We highly recommend using our [BaseChart](/foundations/data-visualization/for-engineers#basechart) code inside the ChartProvider to ensure that the chart is rendered correctly and state is correctly stored. ## Examples diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx b/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/chart-types.mdx similarity index 88% rename from packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx rename to packages/paste-website/src/pages/foundations/data-visualization/for-engineers/chart-types.mdx index 36ee511c35..1cf40aff7f 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/chart-types.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/chart-types.mdx @@ -18,6 +18,7 @@ import { ChartProvider } from "@twilio-paste/chart-provider"; import { PageHeaderSeparator } from "@twilio-paste/page-header"; import { Separator } from "@twilio-paste/separator"; import { InlineCode } from "@twilio-paste/inline-code"; +import { Anchor } from "@twilio-paste/anchor"; import { SidebarCategoryRoutes } from "../../../../constants"; import DefaultLayout from "../../../../layouts/DefaultLayout"; @@ -51,7 +52,7 @@ export const getStaticProps = async () => { In progress - As our current data visualization offerings are in progress these documents are subject to change. We will revise and expand these pages when new chart types are supported. + As our current data visualization offerings are in progress these documents are subject to change. We will revise and expand these pages when new chart types are supported. Please raise a GitHub discussion for any feedback or requests. diff --git a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/index.mdx similarity index 96% rename from packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx rename to packages/paste-website/src/pages/foundations/data-visualization/for-engineers/index.mdx index e5e954c906..d4b3187ca3 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/engineering/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/index.mdx @@ -17,6 +17,7 @@ import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; import { PageHeaderSeparator } from "@twilio-paste/page-header"; import { Separator } from "@twilio-paste/separator"; import { InlineCode } from "@twilio-paste/inline-code"; +import { Anchor} from "@twilio-paste/anchor"; import { SidebarCategoryRoutes } from "../../../../constants"; import DefaultLayout from "../../../../layouts/DefaultLayout"; @@ -50,7 +51,7 @@ export const getStaticProps = async () => { In progress - As our current data visualization offerings are in progress these documents are subject to change. We will revise and expand these pages when new features are supported. + As our current data visualization offerings are in progress these documents are subject to change. We will revise and expand these pages when new features are supported. Please raise a GitHub discussion for any feedback or requests. diff --git a/packages/paste-website/src/pages/foundations/data-visualization/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/index.mdx index c9443ee2ee..366f4a2d91 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/index.mdx @@ -67,7 +67,7 @@ This foundation page was created to help establish a familiar and accessible use Paste Chart support - We're actively working on full charting support through a suite of Paste components designed to make it easy to build pre-styled, interactive charts. As we expand these capabilities, we will continue adding more examples and documentation in the Engineering section. We plan to roll out support for additional chart types over time and recommend using our components if they fit your current needs. + We're actively working on full charting support through a suite of Paste components designed to make it easy to build pre-styled, interactive charts. As we expand these capabilities, we will continue adding more examples and documentation in the For engineers section. We plan to roll out support for additional chart types over time and recommend using our components if they fit your current needs. From ba1e786958178968904a6d4d663d50cdb06796b2 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 30 Apr 2025 10:08:43 -0500 Subject: [PATCH 48/54] chore(data-viz): update urls --- .../src/pages/components/chart-provider/index.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 31d3edd6ef..07f8e46cdf 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -66,7 +66,7 @@ For all chart configuration options you can check our code [here](https://github ### Line Chart -Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/engineering/chart-types#line). To view the options available to configure this chart, references the [API](/components/chart-provider/api#linechartconfig). +Below is an example where only the necessary options are deifned. More examples can be found [here](/foundations/data-visualization/for-engineers/chart-types#line). To view the options available to configure this chart, references the [API](/components/chart-provider/api#linechartconfig). Date: Thu, 1 May 2025 09:06:31 -0500 Subject: [PATCH 49/54] Apply suggestions from code review Co-authored-by: Sarah --- .../pages/components/chart-provider/index.mdx | 6 ++-- .../for-engineers/chart-types.mdx | 6 ++-- .../for-engineers/index.mdx | 34 ++++++++++++------- .../foundations/data-visualization/index.mdx | 2 +- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/packages/paste-website/src/pages/components/chart-provider/index.mdx b/packages/paste-website/src/pages/components/chart-provider/index.mdx index 3a4df7fcc9..ade9cc520e 100644 --- a/packages/paste-website/src/pages/components/chart-provider/index.mdx +++ b/packages/paste-website/src/pages/components/chart-provider/index.mdx @@ -52,18 +52,18 @@ export const getStaticProps = async () => { Chart Provider is a wrapper around Highcharts that provides a consistent API for configuring an individual chart instance. This component has no visible elements and is an engineering asset only. It acts as a store for chart options and provides a context for managing chart state. -We highly recommend using our [BaseChart](/foundations/data-visualization/for-engineers#basechart) code inside the ChartProvider to ensure that the chart is rendered correctly and state is correctly stored. +We highly recommend using our [BaseChart](/foundations/data-visualization/for-engineers#basechart) code inside the Chart Provider to ensure that the chart is rendered correctly and state is correctly stored. ## Examples ### Custom charts -You can use the `highchartsOptions` to create unsupported charts by passing the Higcharts config directly to the base chart without modification. We recommend using our wrappers for easier migration and a simpler way of accessing the rendered chart object for building custom interactions. +You can use the `highchartsOptions` prop to create any currently unsupported charts by passing the Highcharts config directly to the base chart without modification. We recommend using our wrappers for easier migration and a simpler way of accessing the rendered chart object for building custom interactions. Compatibility - If you build charts using the Highcharts API it will be unlikely that our Paste data visualization components will function correctly as they depend on helper functions and event tracking that we enrich the default options with. + If you build charts using the Highcharts API directly it will be unlikely that our Paste data visualization components will function correctly as they depend on helper functions and event tracking that we enrich the default options with. diff --git a/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/chart-types.mdx b/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/chart-types.mdx index 1cf40aff7f..f6cb8046f3 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/chart-types.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/chart-types.mdx @@ -1,5 +1,5 @@ export const meta = { - title: "Data Visualization", + title: "Chart types", description: "Display the supported chart types for the Paste Data Visualization library with coded examples.", slug: "/foundations/data-visualization/engineering/chart-types", }; @@ -52,11 +52,11 @@ export const getStaticProps = async () => { In progress - As our current data visualization offerings are in progress these documents are subject to change. We will revise and expand these pages when new chart types are supported. Please raise a GitHub discussion for any feedback or requests. + As our current data visualization offerings are in progress, these guidelines may change. We will update these pages when new features are supported. Please raise a GitHub discussion for any feedback or requests. -### Custom +## Custom { In progress - As our current data visualization offerings are in progress these documents are subject to change. We will revise and expand these pages when new features are supported. Please raise a GitHub discussion for any feedback or requests. + As our current data visualization offerings are in progress, these guidelines may change. We will update these pages when new features are supported. Please raise a GitHub discussion for any feedback or requests. -Our charting components are designed to work seamlessly with Highcharts. However, due to licensing restrictions, we cannot include Highcharts directly in our library. This limitation creates challenges when developing components for a library we cannot directly interact with. +Our charting components are designed to work seamlessly with Highcharts. However, due to licensing restrictions, we cannot include Highcharts directly in the Paste library. -To address this, we have created components and wrappers that simplify the Highcharts API. These tools expose various props, allowing you to configure charts through a streamlined and user-friendly interface. The props are transformed into objects that Highcharts can interpret, and our components automatically apply styles to the charts for a consistent appearance on a chart type bases. Global styles will be set in the `BaseChart` using our existing hook. +To address this, we have created components and wrappers that simplify the Highcharts API. These tools expose various props, allowing you to configure charts through a streamlined and user-friendly interface. The props are transformed into objects that Highcharts can interpret, and our components automatically apply consistent styles to the charts. Global styles will be set in the `BaseChart` using our existing hook. ## Licensing -Paste does not provide a license for Twilio usage. Licenses are acquired on an application level. If you are developing in one of our existing products it is highly likely licenses are already purchased. If you are creating a new application you may need to acquire a new license. If you need further information you can reach out to us via [GitHub discussions](https://github.com/twilio-labs/paste/discussions/new?category=q-a) or the Procurement team. +Paste does not provide a license for Twilio usage. Licenses are acquired on an application level. For 2025, licenses have already been purchased for these applications: + +- Twilio Admin +- Twilio Console +- Twilio Flex +- Twilio Segment +- Twilio SendGrid + +If you want to use the Paste charting components in another application, you'll need to acquire a new license. If you're a Twilio employee and need further information, you can reach out to us via [GitHub discussions](https://github.com/twilio-labs/paste/discussions/new?category=q-a) or the Twilio Procurement team. ## Setup -To ensure our components function correctly, some initial configuration is required in your project. This seciton will cover: +To ensure our components function correctly, some initial setup is required in your project, including: + - Storing and retrieving rendered chart objects. -- Adding any additional modules required for additional functionality such as gauges, exporting etc. +- Adding any additional modules required for additional functionality such as gauges, exporting, etc. -You will need to include a component that retrieves the chart configuration from our [ChartProvider](/components/chart-provider)'s context and passes it to Highcharts. This component must also capture the rendered chart and store it in the Chart Provider context. +You will need to include a component that retrieves the chart configuration from a [Chart Provider](/components/chart-provider)'s context and passes it to Highcharts. This component must also capture the rendered chart and store it in the Chart Provider context. -Storing the rendered chart is essential for several reasons. It allows us to determine the positioning of elements relative to the screen, enabling the placement of components like tooltips. Additionally, it facilitates triggering update functions on the chart for interactions such as zooming or toggling the visibility of series through a legend component. +Storing the rendered chart is essential for several reasons. It allows us to determine the positioning of elements relative to the screen, enabling the placement of components like Tooltips. Additionally, it facilitates triggering update functions on the chart for interactions such as zooming or toggling the visibility of series through a legend component. ### BaseChart @@ -79,9 +88,10 @@ We recommend copying the below code and creating an instance of it in your appli - Modules subject to change - As we expand our supported charts you will need to maintain this file to include any required modules for the new charts or functionality of our components to work correctly. The change will look like the following: + Modules are subject to change + As we expand our supported charts you will need to maintain this file to include any required modules for the new charts or functionality of our components to work correctly. For example, you might change this line of code from this: applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule); + To this: applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule, HighchartsSankeyModule, ...); @@ -139,9 +149,9 @@ export const BaseChart = React.memo(Chart); We use React Context to store the rendered chart object to use in our components. When talking about the chart context we do not only mean the rendered object but also the initial configuration. You will need to pass data to the context for the `BaseChart` to read and use. -Each individual chart instance will be wrapped in a [ChartProvider](/components/chart-provider) which sets the initial configuration and apply chart specific styles. +Each individual chart instance must be wrapped in a [Chart Provider](/components/chart-provider) which sets the initial configuration and applies chart-specific styles. -An individual chart instance does not mean a chart only. It may also mean chart titles, legends, tooltips and any other component that does not sit in or on the chart canvas. In simpler terms, it is a container that wraps not only the Highcharts elements but any of our Paste components that interact with that chart and canvas. +An individual chart instance doesn't only contain a chart. It also contains chart titles, legends, tooltips, and any other component that's not part of the chart canvas. In simpler terms, it is a container that wraps not only the Highcharts elements, but also any of our Paste components that interact with that chart and canvas. diff --git a/packages/paste-website/src/pages/foundations/data-visualization/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/index.mdx index 366f4a2d91..f81fd69f82 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/index.mdx @@ -65,7 +65,7 @@ This foundation page was created to help establish a familiar and accessible use - Paste Chart support + Paste chart support We're actively working on full charting support through a suite of Paste components designed to make it easy to build pre-styled, interactive charts. As we expand these capabilities, we will continue adding more examples and documentation in the For engineers section. We plan to roll out support for additional chart types over time and recommend using our components if they fit your current needs. From c9109cf041079263c39caa71a8f888cef0731360 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Thu, 1 May 2025 09:06:51 -0500 Subject: [PATCH 50/54] chore(data-viz): addressed PR comments --- .../components/site-wrapper/sidebar/SidebarNavigation.tsx | 4 +++- .../data-visualization/for-engineers/index.mdx | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx index edd93a3fc0..7b7ce2a235 100644 --- a/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx +++ b/packages/paste-website/src/components/site-wrapper/sidebar/SidebarNavigation.tsx @@ -141,7 +141,9 @@ const SiteSidebarNavigation = (): JSX.Element => { buttonText="For engineers" categoryRoute={`${SidebarCategoryRoutes.DATA_VISUALIZATION}/for-engineers`} > - Overview + + Getting started + Chart types diff --git a/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/index.mdx b/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/index.mdx index d4b3187ca3..62c4a6e4c4 100644 --- a/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/index.mdx +++ b/packages/paste-website/src/pages/foundations/data-visualization/for-engineers/index.mdx @@ -1,7 +1,7 @@ export const meta = { - title: "Data Visualization", + title: "Getting started", description: "An overview of integrating Highcharts with Paste's data visualization components, including setup, licensing, and chart context.", - slug: "/foundations/data-visualization/engineering/", + slug: "/foundations/data-visualization/for-engineers/", }; import Image from "next/image"; @@ -66,8 +66,8 @@ Paste does not provide a license for Twilio usage. Licenses are acquired on an a ## Setup To ensure our components function correctly, some initial configuration is required in your project. This seciton will cover: -- Storing and retrieving rendered chart objects. - Adding any additional modules required for additional functionality such as gauges, exporting etc. +- Storing and retrieving rendered chart objects. You will need to include a component that retrieves the chart configuration from our [ChartProvider](/components/chart-provider)'s context and passes it to Highcharts. This component must also capture the rendered chart and store it in the Chart Provider context. @@ -135,7 +135,7 @@ const Chart: React.FC = () => { export const BaseChart = React.memo(Chart); ``` -## Chart context +### Chart context We use React Context to store the rendered chart object to use in our components. When talking about the chart context we do not only mean the rendered object but also the initial configuration. You will need to pass data to the context for the `BaseChart` to read and use. From 27a3b5f5fa545ca9c871ac0dc635b8ac88e93ca4 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Mon, 19 May 2025 10:03:23 -0500 Subject: [PATCH 51/54] fix(e2e): chage order of disclosure opening to account for multiple data-visualization --- cypress/integration/sidebar-navigation/index.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/sidebar-navigation/index.spec.ts b/cypress/integration/sidebar-navigation/index.spec.ts index 610a1e4c50..bc561b654c 100644 --- a/cypress/integration/sidebar-navigation/index.spec.ts +++ b/cypress/integration/sidebar-navigation/index.spec.ts @@ -1,13 +1,13 @@ const sidebarNavigationDisclosures = [ "introduction", "foundations", + "components", "data-visualization", "for-designers", "for-engineers", "contributing", "content", "patterns", - "components", "combobox", "icon", "primitives", From 7b12274d2ab1dc4c499a60651a698dc41172864f Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 28 May 2025 10:39:37 -0500 Subject: [PATCH 52/54] fix(data-viz): toolitp text color --- .../data-visualization/src/usePasteHighchartsTheme.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/paste-libraries/data-visualization/src/usePasteHighchartsTheme.tsx b/packages/paste-libraries/data-visualization/src/usePasteHighchartsTheme.tsx index c671813e3a..10d37bfdd0 100644 --- a/packages/paste-libraries/data-visualization/src/usePasteHighchartsTheme.tsx +++ b/packages/paste-libraries/data-visualization/src/usePasteHighchartsTheme.tsx @@ -112,7 +112,7 @@ export const usePasteHighchartsTheme = (options: Highcharts.Options): Highcharts padding: 12, style: { fontFamily: context.fonts.fontFamilyText, - color: context.textColors.colorText, + color: context.textColors.colorTextInverse, fontSize: context.fontSizes.fontSize30, }, }, From a68a35a18238dc0beaa3cefb3d5a7412d65707d3 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 28 May 2025 10:48:42 -0500 Subject: [PATCH 53/54] feat(ci): fix tests --- .../__test__/__snapshots__/index.spec.tsx.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/paste-libraries/data-visualization/__test__/__snapshots__/index.spec.tsx.snap b/packages/paste-libraries/data-visualization/__test__/__snapshots__/index.spec.tsx.snap index ea5fab8452..24c4c27188 100644 --- a/packages/paste-libraries/data-visualization/__test__/__snapshots__/index.spec.tsx.snap +++ b/packages/paste-libraries/data-visualization/__test__/__snapshots__/index.spec.tsx.snap @@ -137,7 +137,7 @@ Object { "borderWidth": "1px", "padding": 12, "style": Object { - "color": "rgb(18, 28, 45)", + "color": "rgb(255, 255, 255)", "fontFamily": "'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif", "fontSize": "0.875rem", }, @@ -240,7 +240,7 @@ Object { "borderWidth": "1px", "padding": 12, "style": Object { - "color": "rgb(18, 28, 45)", + "color": "rgb(255, 255, 255)", "fontFamily": "'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif", "fontSize": "0.875rem", }, From 9469de0afd1fab2b55ad00e83296bafd4d7ae0d0 Mon Sep 17 00:00:00 2001 From: Kristian Antrobus Date: Wed, 18 Jun 2025 09:47:50 -0500 Subject: [PATCH 54/54] chore(ci): fix yarn lock --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index dc70c41e1c..c180aa6dfb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12199,7 +12199,7 @@ __metadata: languageName: unknown linkType: soft -"@twilio-paste/data-visualization-library@^6.0.2, @twilio-paste/data-visualization-library@workspace:packages/paste-libraries/data-visualization": +"@twilio-paste/data-visualization-library@^6.0.1, @twilio-paste/data-visualization-library@^6.0.2, @twilio-paste/data-visualization-library@workspace:packages/paste-libraries/data-visualization": version: 0.0.0-use.local resolution: "@twilio-paste/data-visualization-library@workspace:packages/paste-libraries/data-visualization" dependencies: