diff --git a/packages/charts/README.md b/packages/charts/README.md new file mode 100644 index 0000000000..d72e51de4c --- /dev/null +++ b/packages/charts/README.md @@ -0,0 +1,7 @@ +# Shoreline Charts + +`shoreline-components` and `echarts` are peer dependencies of `shoreline-charts` + +```sh +pnpm add @vtex/shoreline echarts @vtex/shoreline-charts +``` diff --git a/packages/charts/package.json b/packages/charts/package.json new file mode 100644 index 0000000000..95405b30d9 --- /dev/null +++ b/packages/charts/package.json @@ -0,0 +1,56 @@ +{ + "name": "@vtex/shoreline-charts", + "description": "Shoreline datavis library", + "version": "0.0.0", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org" + }, + "files": [ + "dist" + ], + "exports": { + ".": { + "require": "./dist/index.js", + "import": "./dist/index.mjs", + "types": "./dist/index.d.ts" + }, + "./css": "./dist/index.css" + }, + "engines": { + "node": ">=16" + }, + "scripts": { + "prebuild": "rm -rf dist", + "dev": "tsup --watch", + "build": "tsup" + }, + "repository": { + "directory": "packages/charts", + "type": "git", + "url": "git+https://github.com/vtex/shoreline.git" + }, + "bugs": { + "url": "https://github.com/vtex/shoreline/issues" + }, + "peerDependencies": { + "@vtex/shoreline": "1.x", + "echarts": "5.x", + "react": "18.x", + "react-dom": "18.x" + }, + "devDependencies": { + "@types/lodash": "^4.17.4", + "@vtex/shoreline": "workspace:*", + "echarts": "5.5.0" + }, + "dependencies": { + "@vtex/shoreline-utils": "workspace:*", + "echarts-for-react": "^3.0.2", + "lodash": "^4.17.21", + "vitest-canvas-mock": "^0.3.3" + } +} diff --git a/packages/charts/src/components/chart/chart.tsx b/packages/charts/src/components/chart/chart.tsx new file mode 100644 index 0000000000..410a0672b9 --- /dev/null +++ b/packages/charts/src/components/chart/chart.tsx @@ -0,0 +1,111 @@ +import { + useRef, + useEffect, + useMemo, + forwardRef, + useImperativeHandle, + type ComponentPropsWithRef, + useCallback, +} from 'react' +import type { EChartsOption, SetOptionOpts } from 'echarts' +import ReactECharts, { type EChartsInstance } from 'echarts-for-react' +import type * as echarts from 'echarts' + +import { defaultTheme } from '../../theme/themes' +import type { ChartConfig } from '../../types/chart' +import { getChartOptions } from '../../utils/chart' +import { canUseDOM } from '@vtex/shoreline-utils' +import { DEFAULT_LOADING_SPINNER } from '../../theme/chartStyles' + +/** + * Render a Shoreline Chart with echarts + * @see https://echarts.apache.org/en/index.html + */ +export const Chart = forwardRef( + function Charts(props, ref) { + const { + option, + settings, + loading = false, + loadingConfig = DEFAULT_LOADING_SPINNER, + chartConfig, + style, + ...otherProps + } = props + + const chartRef = useRef(null) + + useImperativeHandle(ref, () => { + if (chartRef.current) { + return chartRef.current.getEchartsInstance() + } + return undefined + }) + + const chartOptions: EChartsOption = useMemo(() => { + const { type, variant } = chartConfig + return getChartOptions(option, type, variant) || option + }, [option, chartConfig]) + + const handleResize = useCallback(() => { + if (chartRef.current) { + chartRef.current.getEchartsInstance().resize() + } + }, [chartRef]) + + useEffect(() => { + if (!canUseDOM) return + + window.addEventListener('resize', handleResize) + return () => { + window.removeEventListener('resize', handleResize) + } + }, [handleResize, canUseDOM]) + + return ( +
+ instance.resize()} + {...otherProps} + /> +
+ ) + } +) + +export interface ChartsOptions { + /** + * Echarts options for the chart + */ + option: EChartsOption + /** + * Echarts settings + */ + settings?: SetOptionOpts + /** + * Wether is loading + * @default false + */ + loading?: boolean + /** + * Options for customize the chart loading + * @default false + */ + loadingConfig?: EChartsInstance['showLoading'] + /** + * Configs containing type of chart and its variants, each variant is a pre-defined chart style for each type + * @default default + */ + chartConfig: ChartConfig +} + +export type ChartProps = ChartsOptions & ComponentPropsWithRef<'div'> diff --git a/packages/charts/src/components/chart/index.ts b/packages/charts/src/components/chart/index.ts new file mode 100644 index 0000000000..57f27f47ca --- /dev/null +++ b/packages/charts/src/components/chart/index.ts @@ -0,0 +1 @@ +export * from './chart' diff --git a/packages/charts/src/components/index.ts b/packages/charts/src/components/index.ts new file mode 100644 index 0000000000..adc123487f --- /dev/null +++ b/packages/charts/src/components/index.ts @@ -0,0 +1,2 @@ +export * from './tooltip' +export * from './chart' diff --git a/packages/charts/src/components/tooltip/index.ts b/packages/charts/src/components/tooltip/index.ts new file mode 100644 index 0000000000..fa5a7e5245 --- /dev/null +++ b/packages/charts/src/components/tooltip/index.ts @@ -0,0 +1 @@ +export * from './tooltip' diff --git a/packages/charts/src/components/tooltip/tooltip.tsx b/packages/charts/src/components/tooltip/tooltip.tsx new file mode 100644 index 0000000000..c1dce0b45d --- /dev/null +++ b/packages/charts/src/components/tooltip/tooltip.tsx @@ -0,0 +1,45 @@ +import type { TooltipComponentFormatterCallbackParams } from 'echarts' +import { renderToStaticMarkup } from 'react-dom/server' +import '../../theme/components/tooltip.css' + +export default function ChartTooltip({ params }: ChartTooltipProps) { + return ( +
+ {Array.isArray(params) ? ( + params.map((param) => ( + + )) + ) : ( + + )} +
+ ) +} + +export function ChartTooltipBase({ params }: { params: any }) { + return ( + <> +

{params.name}

+
+
+ + {params.seriesName} +
+ {params.value} +
+ + ) +} + +export const getTooltipStaticString = ( + params: TooltipComponentFormatterCallbackParams +) => renderToStaticMarkup() + +export interface ChartTooltipProps { + params: TooltipComponentFormatterCallbackParams +} diff --git a/packages/charts/src/index.ts b/packages/charts/src/index.ts new file mode 100644 index 0000000000..cb64ac1b52 --- /dev/null +++ b/packages/charts/src/index.ts @@ -0,0 +1 @@ +export * from './components' diff --git a/packages/charts/src/stories/bar-charts.stories.tsx b/packages/charts/src/stories/bar-charts.stories.tsx new file mode 100644 index 0000000000..65db7ad336 --- /dev/null +++ b/packages/charts/src/stories/bar-charts.stories.tsx @@ -0,0 +1,122 @@ +// biome-ignore lint/correctness/noUnusedImports: +import React from 'react' +import { Chart } from '../index' +import { compactNumber } from '../utils/format' +import type { StoryObj } from '@storybook/react' + +const Bar = { + title: 'Charts/bar', + component: Chart, +} +export default Bar + +type Story = StoryObj + +export const Basic: Story = { + args: { + option: { + xAxis: { + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + }, + series: [{ data: [1, 2, 3, 4, 5, 6, 7] }], + }, + chartConfig: { type: 'bar' }, + style: { height: 550 }, + }, +} + +export const Loading: Story = { + render: (args) => { + const { option, chartConfig, loading } = args + + return ( + + ) + }, + args: { + option: { + xAxis: { + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + }, + series: [{ data: [1, 2, 3, 4, 5, 6, 7] }], + }, + chartConfig: { type: 'bar' }, + style: { height: 550 }, + loading: true, + }, +} +export const MultiSeries: Story = { + args: { + option: { + xAxis: { + data: ['Mon', 'Tue', 'Wed'], + }, + series: [ + { data: [3, 2, 3, 4], name: 'Series 1' }, + { data: [1, 4, 2, 3], name: 'Series 2' }, + { data: [2, 1, 4, 1], name: 'Series 3' }, + ], + }, + chartConfig: { type: 'bar' }, + style: { height: 550 }, + }, +} +export const WithHugeNumbers: Story = { + args: { + option: { + xAxis: { + data: ['Mon', 'Tue', 'Wed'], + }, + yAxis: { + axisLabel: { + formatter: (value: number) => compactNumber(value), + }, + }, + series: [ + { + data: [12344441, 62346346, 97346346], + name: 'Series 1', + }, + ], + }, + chartConfig: { type: 'bar' }, + style: { height: 550 }, + }, +} + +export const Horizontal: Story = { + args: { + option: { + xAxis: { + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun', 'Test'], + }, + series: [ + { data: [1, 2, 3, 4, 5, 6, 7, 8] }, + { data: [1, 4, 2, 1, 4, 3, 5, 9] }, + ], + }, + chartConfig: { type: 'bar', variant: 'horizontal' }, + style: { height: 550 }, + }, +} + +export const MultiType: Story = { + args: { + option: { + xAxis: { + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + }, + series: [ + { data: [1, 2, 3, 4, 5, 6, 7] }, + { data: [1, 4, 2, 1, 4, 3, 5], type: 'line' }, + ], + }, + chartConfig: { type: 'bar', variant: 'default' }, + style: { height: 550 }, + }, +} diff --git a/packages/charts/src/tests/__fixtures__/chartData.ts b/packages/charts/src/tests/__fixtures__/chartData.ts new file mode 100644 index 0000000000..796ecd85dc --- /dev/null +++ b/packages/charts/src/tests/__fixtures__/chartData.ts @@ -0,0 +1,8 @@ +export const BAR_CHART_DATA = { + xAxis: { + weekdays: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + }, + series: { + dayNumbers: [1, 2, 3, 4, 5, 6, 7], + }, +} diff --git a/packages/charts/src/tests/charts.test.tsx b/packages/charts/src/tests/charts.test.tsx new file mode 100644 index 0000000000..26bacdfaee --- /dev/null +++ b/packages/charts/src/tests/charts.test.tsx @@ -0,0 +1,40 @@ +import { + describe, + expect, + test, + render, + waitFor, + screen, +} from '@vtex/shoreline-test-utils' +import { Chart } from '../components/chart' +import { BAR_CHART_DATA } from './__fixtures__/chartData' +// biome-ignore lint/correctness/noUnusedImports: +import React from 'react' + +describe('@vtex.shoreline-charts bar chart tests', () => { + test('renders the bar chart with correct data', async () => { + const { container } = render( + + ) + + const divChartContainer = container.querySelector('[data-sl-chart]') + await waitFor(() => expect(divChartContainer).toBeInTheDocument()) + + BAR_CHART_DATA.xAxis.weekdays.forEach((value) => + waitFor(() => expect(screen.queryByText(value)).toBeInTheDocument()) + ) + + BAR_CHART_DATA.series.dayNumbers.forEach((value) => + waitFor(() => expect(screen.queryByText(value)).toBeInTheDocument()) + ) + }) +}) diff --git a/packages/charts/src/tests/vitest.config.ts b/packages/charts/src/tests/vitest.config.ts new file mode 100644 index 0000000000..29984e1013 --- /dev/null +++ b/packages/charts/src/tests/vitest.config.ts @@ -0,0 +1,20 @@ +import { vi } from 'vitest' +import 'vitest-canvas-mock' + +vi.mock('echarts', async () => { + const echarts = await vi.importActual('echarts') + return { + ...echarts, + init: vi.fn(() => { + return { + setOption: vi.fn(), + resize: vi.fn(), + getOption: vi.fn(), + dispose: vi.fn(), + clear: vi.fn(), + on: vi.fn(), + off: vi.fn(), + } + }), + } +}) diff --git a/packages/charts/src/theme/chartStyles.ts b/packages/charts/src/theme/chartStyles.ts new file mode 100644 index 0000000000..348dae2011 --- /dev/null +++ b/packages/charts/src/theme/chartStyles.ts @@ -0,0 +1,87 @@ +import type { EChartsOption } from 'echarts' +import type { DefaultChartStyles } from '../types/chart' +import type { EChartsInstance } from 'echarts-for-react' +import { defaultSpinnerColor } from './colors' +import { getTooltipStaticString } from '../components/tooltip' + +const TOOLTIP_OPTIONS: EChartsOption['tooltip'] = { + trigger: 'item', + borderWidth: 1, + borderColor: 'var(--sl-color-gray-4)', + formatter: (params) => { + return getTooltipStaticString(params) + }, +} +export const BAR_CHART_LEGEND_DEFAULT_STYLE: EChartsOption['legend'] = { + orient: 'horizontal', + left: 'auto', + bottom: 0, + align: 'left', + itemWidth: 16, + itemHeight: 16, + padding: 0, + itemGap: 20, +} + +export const BAR_CHART_GRID_DEFAULT_STYLE: EChartsOption['grid'] = { + left: 'auto', + right: '0', + top: '5', + bottom: '7%', + containLabel: true, +} + +export const CHART_STYLES: DefaultChartStyles = { + bar: { + default: { + xAxis: { + type: 'category', + }, + yAxis: { + type: 'value', + }, + series: { + type: 'bar', + }, + barGap: '20%', + barCategoryGap: '55%', + legend: BAR_CHART_LEGEND_DEFAULT_STYLE, + grid: BAR_CHART_GRID_DEFAULT_STYLE, + barMaxWidth: 60, + barMinWidth: 15, + tooltip: TOOLTIP_OPTIONS, + }, + horizontal: { + xAxis: { + type: 'value', + }, + yAxis: { + type: 'category', + }, + barGap: '20%', + barCategoryGap: '55%', + legend: BAR_CHART_LEGEND_DEFAULT_STYLE, + grid: BAR_CHART_GRID_DEFAULT_STYLE, + barMaxWidth: 60, + barMinWidth: 15, + tooltip: TOOLTIP_OPTIONS, + series: { + type: 'bar', + itemStyle: { + borderRadius: [0, 4, 4, 0], + }, + }, + }, + }, + line: { + default: {}, + base: {}, + }, +} + +export const DEFAULT_LOADING_SPINNER: EChartsInstance['showLoading'] = { + text: '', + spinnerRadius: 10, + lineWidth: 3, + color: defaultSpinnerColor, +} diff --git a/packages/charts/src/theme/colors.ts b/packages/charts/src/theme/colors.ts new file mode 100644 index 0000000000..587ecd074d --- /dev/null +++ b/packages/charts/src/theme/colors.ts @@ -0,0 +1,20 @@ +import { presetSunrise } from '@vtex/shoreline' +import { parseTokens } from '@vtex/shoreline-utils' + +export const colors = parseTokens({ + tokens: presetSunrise?.tokens?.color ?? {}, +}) + +export const defaultColorPreset = [ + colors['--sl-blue-8'], + colors['--sl-orange-6'], + colors['--sl-purple-9'], +] + +export const defaultChartColorConfig = { + lineColor: colors['--sl-gray-6'], + textSoft: colors['--sl-gray-9'], + bgLineColor: colors['--sl-gray-3'], +} + +export const defaultSpinnerColor = colors['--sl-blue-8'] diff --git a/packages/charts/src/theme/components/index.css b/packages/charts/src/theme/components/index.css new file mode 100644 index 0000000000..1a89c4c462 --- /dev/null +++ b/packages/charts/src/theme/components/index.css @@ -0,0 +1 @@ +@import "tooltip.css"; diff --git a/packages/charts/src/theme/components/tooltip.css b/packages/charts/src/theme/components/tooltip.css new file mode 100644 index 0000000000..c023198575 --- /dev/null +++ b/packages/charts/src/theme/components/tooltip.css @@ -0,0 +1,28 @@ +[data-sl-chart-tooltip] { + background-color: var(--sl-color-gray-0); + border-radius: 4px; + min-width: 100px; +} +[data-sl-chart-tooltip-title] { + font-weight: bold; +} +[data-sl-chart-tooltip-data-container] { + display: flex; + justify-content: space-between; + padding: var(--sl-space-2) 0px; +} +[data-sl-chart-tooltip-data-serie-container] { + display: flex; + align-items: center; +} +[data-sl-chart-tooltip-data-serie-label-box] { + width: 16px; + height: 16px; + display: inline-block; + margin-right: var(--sl-space-1); + border-radius: var(--sl-space-1); +} +[data-sl-chart-tooltip-data-serie-value] { + font-weight: bold; + margin-left: var(--sl-space-gap); +} diff --git a/packages/charts/src/theme/themes.ts b/packages/charts/src/theme/themes.ts new file mode 100644 index 0000000000..956844c456 --- /dev/null +++ b/packages/charts/src/theme/themes.ts @@ -0,0 +1,39 @@ +import { defaultChartColorConfig, defaultColorPreset } from './colors' + +export const defaultTheme = { + color: defaultColorPreset, + categoryAxis: { + axisTick: { + show: false, + }, + axisLine: { + show: true, + lineStyle: { + color: defaultChartColorConfig.lineColor, + }, + }, + axisLabel: { + color: defaultChartColorConfig.textSoft, + }, + }, + valueAxis: { + type: 'value', + axisLine: { + show: false, + }, + axisLabel: { + color: defaultChartColorConfig.textSoft, + }, + splitLine: { + lineStyle: { + color: defaultChartColorConfig.bgLineColor, + width: 1, + }, + }, + }, + bar: { + itemStyle: { + borderRadius: [4, 4, 0, 0], + }, + }, +} diff --git a/packages/charts/src/types/chart.ts b/packages/charts/src/types/chart.ts new file mode 100644 index 0000000000..3628b685cb --- /dev/null +++ b/packages/charts/src/types/chart.ts @@ -0,0 +1,21 @@ +import type { EChartsOption } from 'echarts' + +export type BarChartVariants = 'default' | 'horizontal' + +export type LineChartVariants = 'default' | 'base' + +export type LineChartConfig = { type: 'line'; variant?: LineChartVariants } +export type BarChartConfig = { type: 'bar'; variant?: BarChartVariants } + +export type ChartConfig = BarChartConfig | BarChartConfig + +export type ChartLoadingConfig = { + text?: string + color?: string + textColor?: string + fontSize?: number +} +export type DefaultChartStyles = { + bar: Record + line: Record +} diff --git a/packages/charts/src/utils/chart.ts b/packages/charts/src/utils/chart.ts new file mode 100644 index 0000000000..faf7b3debe --- /dev/null +++ b/packages/charts/src/utils/chart.ts @@ -0,0 +1,50 @@ +import type { EChartsOption, SeriesOption } from 'echarts' +import { CHART_STYLES } from '../theme/chartStyles' +import type { ChartConfig } from '../types/chart' +import { merge } from '@vtex/shoreline-utils' +import { cloneDeep } from 'lodash' + +export const buildDefaultSerie = ( + serie: SeriesOption | SeriesOption[], + defaultStyle: EChartsOption +): SeriesOption => { + const seriesClone = cloneDeep(serie) + const defaultStylesClone = cloneDeep(defaultStyle.series) + const serieMerged = merge(defaultStylesClone, seriesClone) as SeriesOption + + return serieMerged +} + +export const formatSeries = ( + series: SeriesOption | SeriesOption[] | undefined, + defaultStyle: EChartsOption +) => { + if (!series) return + if (Array.isArray(series)) { + return series.map((serie) => buildDefaultSerie(serie, defaultStyle)) + } + + return buildDefaultSerie(series, defaultStyle) +} + +export const getChartOptions = ( + options: EChartsOption, + type: ChartConfig['type'], + variant: ChartConfig['variant'] +): EChartsOption | undefined => { + if (!options) return + const { series, ...rest } = options + const chartStyleType = CHART_STYLES[type] + + const defaultStyle = variant + ? chartStyleType[variant] + : chartStyleType.default + + const { series: defaultSeries, ...defaultRest } = defaultStyle + + const formattedSeries = formatSeries(series, defaultStyle) + + const mergedOptions = merge(defaultRest, rest) + + return { ...mergedOptions, series: formattedSeries } +} diff --git a/packages/charts/src/utils/format.ts b/packages/charts/src/utils/format.ts new file mode 100644 index 0000000000..e70184768a --- /dev/null +++ b/packages/charts/src/utils/format.ts @@ -0,0 +1,8 @@ +export const compactNumber = (number: number) => { + const formatter = new Intl.NumberFormat('en-US', { + notation: 'compact', + maximumFractionDigits: 2, + }) + + return formatter.format(number) +} diff --git a/packages/charts/tsconfig.json b/packages/charts/tsconfig.json new file mode 100644 index 0000000000..9907687682 --- /dev/null +++ b/packages/charts/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "declarationDir": "declarations" + }, + "include": ["./src"], + "exclude": [ + "node_modules", + "dist", + "**/*.test.*", + "**/*.stories.*", + "**/*test-utils*" + ] +} diff --git a/packages/charts/tsup.config.ts b/packages/charts/tsup.config.ts new file mode 100644 index 0000000000..140dfa0fbe --- /dev/null +++ b/packages/charts/tsup.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['cjs', 'esm'], + external: ['react'], + splitting: false, + sourcemap: true, + clean: true, + dts: true, + banner: { + js: "'use client'", + }, +}) diff --git a/packages/docs/examples/chart-bar.tsx b/packages/docs/examples/chart-bar.tsx new file mode 100644 index 0000000000..f1953171cf --- /dev/null +++ b/packages/docs/examples/chart-bar.tsx @@ -0,0 +1,16 @@ +import { Chart } from '@vtex/shoreline-charts' + +export default function Example() { + return ( + + ) +} diff --git a/packages/docs/package.json b/packages/docs/package.json index e205d3514c..7e170d67c2 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -23,6 +23,7 @@ "@vtex/shoreline": "workspace:*", "@vtex/shoreline-ts-table": "workspace:*", "@vtex/shoreline-utils": "workspace:*", + "@vtex/shoreline-charts": "workspace:*", "fs-extra": "11.2.0", "google": "link:@next/third-parties/google", "next": "^15.0.0", diff --git a/packages/docs/pages/_app.tsx b/packages/docs/pages/_app.tsx index a8d471aa83..792b1fd1ae 100644 --- a/packages/docs/pages/_app.tsx +++ b/packages/docs/pages/_app.tsx @@ -1,6 +1,7 @@ import type { AppProps } from 'next/app' import { GoogleAnalytics } from '@next/third-parties/google' import '@vtex/shoreline/themes/sunrise/unlayered' +import '@vtex/shoreline-charts/css' import './global.css' export default function MyApp({ Component, pageProps }: AppProps) { diff --git a/packages/docs/pages/_meta.ts b/packages/docs/pages/_meta.ts index f2564974c0..94bb7012c3 100644 --- a/packages/docs/pages/_meta.ts +++ b/packages/docs/pages/_meta.ts @@ -19,6 +19,10 @@ export default { title: 'Foundations', type: 'page', }, + charts: { + title: 'Charts', + type: 'page', + }, 'eng-onsite-2024': { display: 'hidden', theme: { diff --git a/packages/docs/pages/charts/_meta.ts b/packages/docs/pages/charts/_meta.ts new file mode 100644 index 0000000000..1ce84b5f83 --- /dev/null +++ b/packages/docs/pages/charts/_meta.ts @@ -0,0 +1,4 @@ +export default { + index: { title: 'All Charts', theme: { layout: 'full' } }, + bar: 'Bar Chart', +} diff --git a/packages/docs/pages/charts/bar.mdx b/packages/docs/pages/charts/bar.mdx new file mode 100644 index 0000000000..ea923fc387 --- /dev/null +++ b/packages/docs/pages/charts/bar.mdx @@ -0,0 +1,5 @@ +# Bar chart + + +## Examples + diff --git a/packages/docs/pages/charts/bar/best-practices.mdx b/packages/docs/pages/charts/bar/best-practices.mdx new file mode 100644 index 0000000000..3cfbb8dbcb --- /dev/null +++ b/packages/docs/pages/charts/bar/best-practices.mdx @@ -0,0 +1,12 @@ +# Best Practices + +## Properties + +### Variant + +| Value | Usage | Example | +| :--- | :--- | :--- | +| `info` | Message without a clear semantic that doesn't require immediate attention. For example, announcements, product invitations, and progress feedback. | "A new Products experience is available. This version will be discontinued in June 2024." with a Try new version action | +| `critical` | Action that failed due to a technical error or a user error. Include a proposed action or, when it's not possible, explain what to do next. | "There are 2 invoices that could not be processed because of a technical issue" with a Try again action | +| `warning` | Unexpected behavior or something to be cautious about. Consider including a proposed action or explaining what to do next. | "Stores in this account still can't sell to the final customer" with an Activate account action | +| `positive` | Action that matched or surpassed expectations. | "The performance of this seller improved and now meets minimum requirements" with a View performance action | diff --git a/packages/docs/pages/charts/index.mdx b/packages/docs/pages/charts/index.mdx new file mode 100644 index 0000000000..213de42abf --- /dev/null +++ b/packages/docs/pages/charts/index.mdx @@ -0,0 +1,13 @@ +# Components + +import { + allChartsList +} from "../../utils/all-components-list"; +import { pascalCase } from "@vtex/shoreline"; + + + {allChartsList.map((component) => { + let href = `/charts/${component}`; + return ; + })} + diff --git a/packages/docs/public/assets/all-chart-bar.png b/packages/docs/public/assets/all-chart-bar.png new file mode 100644 index 0000000000..656b11ffa6 Binary files /dev/null and b/packages/docs/public/assets/all-chart-bar.png differ diff --git a/packages/docs/scripts/build-props.mjs b/packages/docs/scripts/build-props.mjs index 9bc6f0eae4..9e9ccb64ce 100644 --- a/packages/docs/scripts/build-props.mjs +++ b/packages/docs/scripts/build-props.mjs @@ -11,127 +11,132 @@ const files = [ /** * Primitives */ - getPath('components', 'accessible-icon', 'accessible-icon'), - getPath('components', 'clickable', 'clickable'), - getPath('components', 'clickable', 'clickable-bubble'), - getPath('components', 'combobox', 'combobox'), - getPath('components', 'combobox', 'combobox-provider'), - getPath('components', 'combobox', 'combobox-popover'), - getPath('components', 'combobox', 'combobox-list'), - getPath('components', 'combobox', 'combobox-item'), - getPath('components', 'compose', 'compose'), - getPath('components', 'compose', 'composable'), - getPath('components', 'link-box', 'link-box'), - getPath('components', 'locale', 'locale-provider'), - getPath('components', 'visually-hidden', 'visually-hidden'), + getPath('shoreline', 'components', 'accessible-icon', 'accessible-icon'), + getPath('shoreline', 'components', 'clickable', 'clickable'), + getPath('shoreline', 'components', 'clickable', 'clickable-bubble'), + getPath('shoreline', 'components', 'combobox', 'combobox'), + getPath('shoreline', 'components', 'combobox', 'combobox-provider'), + getPath('shoreline', 'components', 'combobox', 'combobox-popover'), + getPath('shoreline', 'components', 'combobox', 'combobox-list'), + getPath('shoreline', 'components', 'combobox', 'combobox-item'), + getPath('shoreline', 'components', 'compose', 'compose'), + getPath('shoreline', 'components', 'compose', 'composable'), + getPath('shoreline', 'components', 'link-box', 'link-box'), + getPath('shoreline', 'components', 'locale', 'locale-provider'), + getPath('shoreline', 'components', 'visually-hidden', 'visually-hidden'), /** * Components */ - getPath('components', 'alert', 'alert'), - getPath('components', 'bleed', 'bleed'), - getPath('components', 'button', 'button'), - getPath('components', 'center', 'center'), - getPath('components', 'checkbox', 'checkbox'), - getPath('components', 'checkbox', 'checkbox-group'), - getPath('components', 'collection', 'collection'), - getPath('components', 'collection', 'collection-view'), - getPath('components', 'collection', 'collection-row'), - getPath('components', 'confirmation-modal', 'confirmation-modal'), - getPath('components', 'content', 'content'), - getPath('components', 'content', 'container'), - getPath('components', 'contextual-help', 'contextual-help'), - getPath('components', 'divider', 'divider'), - getPath('components', 'drawer', 'drawer-content'), - getPath('components', 'drawer', 'drawer-dismiss'), - getPath('components', 'drawer', 'drawer-footer'), - getPath('components', 'drawer', 'drawer-header'), - getPath('components', 'drawer', 'drawer-heading'), - getPath('components', 'drawer', 'drawer-popover'), - getPath('components', 'drawer', 'drawer-provider'), - getPath('components', 'drawer', 'drawer-trigger'), - getPath('components', 'empty-state', 'empty-state'), - getPath('components', 'empty-state', 'empty-state-actions'), - getPath('components', 'empty-state', 'empty-state-illustration'), - getPath('components', 'field', 'field'), - getPath('components', 'field', 'field-provider'), - getPath('components', 'field', 'field-error'), - getPath('components', 'field', 'field-description'), - getPath('components', 'field', 'field-char-counter'), - getPath('components', 'filter', 'filter'), - getPath('components', 'filter', 'filter-value'), - getPath('components', 'filter', 'filter-trigger'), - getPath('components', 'filter', 'filter-provider'), - getPath('components', 'filter', 'filter-popover'), - getPath('components', 'filter', 'filter-list'), - getPath('components', 'filter', 'filter-list-skeleton'), - getPath('components', 'filter', 'filter-item'), - getPath('components', 'filter', 'filter-item-check'), - getPath('components', 'filter', 'filter-clear'), - getPath('components', 'filter', 'filter-apply'), - getPath('components', 'flex', 'flex'), - getPath('components', 'grid', 'grid'), - getPath('components', 'grid', 'grid-cell'), - getPath('components', 'heading', 'heading'), - getPath('components', 'icon-button', 'icon-button'), - getPath('components', 'input', 'input'), - getPath('components', 'label', 'label'), - getPath('components', 'link', 'link'), - getPath('components', 'menu', 'menu'), - getPath('components', 'menu', 'menu-trigger'), - getPath('components', 'menu', 'menu-separator'), - getPath('components', 'menu', 'menu-provider'), - getPath('components', 'menu', 'menu-popover'), - getPath('components', 'menu', 'menu-item'), - getPath('components', 'modal', 'modal'), - getPath('components', 'modal', 'modal-heading'), - getPath('components', 'modal', 'modal-header'), - getPath('components', 'modal', 'modal-footer'), - getPath('components', 'modal', 'modal-dismiss'), - getPath('components', 'modal', 'modal-content'), - getPath('components', 'page', 'page'), - getPath('components', 'page', 'page-heading'), - getPath('components', 'page', 'page-header'), - getPath('components', 'page', 'page-header-row'), - getPath('components', 'page', 'page-content'), - getPath('components', 'pagination', 'pagination'), - getPath('components', 'popover', 'popover'), - getPath('components', 'popover', 'popover-trigger'), - getPath('components', 'popover', 'popover-provider'), - getPath('components', 'popover', 'popover-dismiss'), - getPath('components', 'radio', 'radio'), - getPath('components', 'radio', 'radio-group'), - getPath('components', 'search', 'search'), - getPath('components', 'select', 'select'), - getPath('components', 'select', 'select-trigger'), - getPath('components', 'select', 'select-provider'), - getPath('components', 'select', 'select-popover'), - getPath('components', 'select', 'select-list'), - getPath('components', 'select', 'select-item'), - getPath('components', 'select', 'select-item-check'), - getPath('components', 'skeleton', 'skeleton'), - getPath('components', 'spinner', 'spinner'), - getPath('components', 'stack', 'stack'), - getPath('components', 'tab', 'tab'), - getPath('components', 'tab', 'tab-provider'), - getPath('components', 'tab', 'tab-panel'), - getPath('components', 'tab', 'tab-list'), - getPath('components', 'table', 'table'), - getPath('components', 'table', 'table-sort-indicator'), - getPath('components', 'table', 'table-row'), - getPath('components', 'table', 'table-header'), - getPath('components', 'table', 'table-header-cell'), - getPath('components', 'table', 'table-cell'), - getPath('components', 'table', 'table-body'), - getPath('components', 'tag', 'tag'), - getPath('components', 'text', 'text'), - getPath('components', 'textarea', 'textarea'), - getPath('components', 'toast', 'toast'), - getPath('components', 'toast', 'toast-stack'), - getPath('components', 'tooltip', 'tooltip'), - getPath('components', 'tooltip', 'tooltip-trigger'), - getPath('components', 'tooltip', 'tooltip-provider'), - getPath('components', 'tooltip', 'tooltip-popover'), - getPath('components', 'tooltip', 'tooltip-arrow'), + getPath('shoreline', 'components', 'alert', 'alert'), + getPath('shoreline', 'components', 'bleed', 'bleed'), + getPath('shoreline', 'components', 'button', 'button'), + getPath('shoreline', 'components', 'center', 'center'), + getPath('shoreline', 'components', 'checkbox', 'checkbox'), + getPath('shoreline', 'components', 'checkbox', 'checkbox-group'), + getPath('shoreline', 'components', 'collection', 'collection'), + getPath('shoreline', 'components', 'collection', 'collection-view'), + getPath('shoreline', 'components', 'collection', 'collection-row'), + getPath( + 'shoreline', + 'components', + 'confirmation-modal', + 'confirmation-modal' + ), + getPath('shoreline', 'components', 'content', 'content'), + getPath('shoreline', 'components', 'content', 'container'), + getPath('shoreline', 'components', 'contextual-help', 'contextual-help'), + getPath('shoreline', 'components', 'divider', 'divider'), + getPath('shoreline', 'components', 'drawer', 'drawer-content'), + getPath('shoreline', 'components', 'drawer', 'drawer-dismiss'), + getPath('shoreline', 'components', 'drawer', 'drawer-footer'), + getPath('shoreline', 'components', 'drawer', 'drawer-header'), + getPath('shoreline', 'components', 'drawer', 'drawer-heading'), + getPath('shoreline', 'components', 'drawer', 'drawer-popover'), + getPath('shoreline', 'components', 'drawer', 'drawer-provider'), + getPath('shoreline', 'components', 'drawer', 'drawer-trigger'), + getPath('shoreline', 'components', 'empty-state', 'empty-state'), + getPath('shoreline', 'components', 'empty-state', 'empty-state-actions'), + getPath('shoreline', 'components', 'empty-state', 'empty-state-illustration'), + getPath('shoreline', 'components', 'field', 'field'), + getPath('shoreline', 'components', 'field', 'field-provider'), + getPath('shoreline', 'components', 'field', 'field-error'), + getPath('shoreline', 'components', 'field', 'field-description'), + getPath('shoreline', 'components', 'field', 'field-char-counter'), + getPath('shoreline', 'components', 'filter', 'filter'), + getPath('shoreline', 'components', 'filter', 'filter-value'), + getPath('shoreline', 'components', 'filter', 'filter-trigger'), + getPath('shoreline', 'components', 'filter', 'filter-provider'), + getPath('shoreline', 'components', 'filter', 'filter-popover'), + getPath('shoreline', 'components', 'filter', 'filter-list'), + getPath('shoreline', 'components', 'filter', 'filter-list-skeleton'), + getPath('shoreline', 'components', 'filter', 'filter-item'), + getPath('shoreline', 'components', 'filter', 'filter-item-check'), + getPath('shoreline', 'components', 'filter', 'filter-clear'), + getPath('shoreline', 'components', 'filter', 'filter-apply'), + getPath('shoreline', 'components', 'flex', 'flex'), + getPath('shoreline', 'components', 'grid', 'grid'), + getPath('shoreline', 'components', 'grid', 'grid-cell'), + getPath('shoreline', 'components', 'heading', 'heading'), + getPath('shoreline', 'components', 'icon-button', 'icon-button'), + getPath('shoreline', 'components', 'input', 'input'), + getPath('shoreline', 'components', 'label', 'label'), + getPath('shoreline', 'components', 'link', 'link'), + getPath('shoreline', 'components', 'menu', 'menu'), + getPath('shoreline', 'components', 'menu', 'menu-trigger'), + getPath('shoreline', 'components', 'menu', 'menu-separator'), + getPath('shoreline', 'components', 'menu', 'menu-provider'), + getPath('shoreline', 'components', 'menu', 'menu-popover'), + getPath('shoreline', 'components', 'menu', 'menu-item'), + getPath('shoreline', 'components', 'modal', 'modal'), + getPath('shoreline', 'components', 'modal', 'modal-heading'), + getPath('shoreline', 'components', 'modal', 'modal-header'), + getPath('shoreline', 'components', 'modal', 'modal-footer'), + getPath('shoreline', 'components', 'modal', 'modal-dismiss'), + getPath('shoreline', 'components', 'modal', 'modal-content'), + getPath('shoreline', 'components', 'page', 'page'), + getPath('shoreline', 'components', 'page', 'page-heading'), + getPath('shoreline', 'components', 'page', 'page-header'), + getPath('shoreline', 'components', 'page', 'page-header-row'), + getPath('shoreline', 'components', 'page', 'page-content'), + getPath('shoreline', 'components', 'pagination', 'pagination'), + getPath('shoreline', 'components', 'popover', 'popover'), + getPath('shoreline', 'components', 'popover', 'popover-trigger'), + getPath('shoreline', 'components', 'popover', 'popover-provider'), + getPath('shoreline', 'components', 'popover', 'popover-dismiss'), + getPath('shoreline', 'components', 'radio', 'radio'), + getPath('shoreline', 'components', 'radio', 'radio-group'), + getPath('shoreline', 'components', 'search', 'search'), + getPath('shoreline', 'components', 'select', 'select'), + getPath('shoreline', 'components', 'select', 'select-trigger'), + getPath('shoreline', 'components', 'select', 'select-provider'), + getPath('shoreline', 'components', 'select', 'select-popover'), + getPath('shoreline', 'components', 'select', 'select-list'), + getPath('shoreline', 'components', 'select', 'select-item'), + getPath('shoreline', 'components', 'select', 'select-item-check'), + getPath('shoreline', 'components', 'skeleton', 'skeleton'), + getPath('shoreline', 'components', 'spinner', 'spinner'), + getPath('shoreline', 'components', 'stack', 'stack'), + getPath('shoreline', 'components', 'tab', 'tab'), + getPath('shoreline', 'components', 'tab', 'tab-provider'), + getPath('shoreline', 'components', 'tab', 'tab-panel'), + getPath('shoreline', 'components', 'tab', 'tab-list'), + getPath('shoreline', 'components', 'table', 'table'), + getPath('shoreline', 'components', 'table', 'table-sort-indicator'), + getPath('shoreline', 'components', 'table', 'table-row'), + getPath('shoreline', 'components', 'table', 'table-header'), + getPath('shoreline', 'components', 'table', 'table-header-cell'), + getPath('shoreline', 'components', 'table', 'table-cell'), + getPath('shoreline', 'components', 'table', 'table-body'), + getPath('shoreline', 'components', 'tag', 'tag'), + getPath('shoreline', 'components', 'text', 'text'), + getPath('shoreline', 'components', 'textarea', 'textarea'), + getPath('shoreline', 'components', 'toast', 'toast'), + getPath('shoreline', 'components', 'toast', 'toast-stack'), + getPath('shoreline', 'components', 'tooltip', 'tooltip'), + getPath('shoreline', 'components', 'tooltip', 'tooltip-trigger'), + getPath('shoreline', 'components', 'tooltip', 'tooltip-provider'), + getPath('shoreline', 'components', 'tooltip', 'tooltip-popover'), + getPath('shoreline', 'components', 'tooltip', 'tooltip-arrow'), /** * ts-table */ @@ -139,18 +144,29 @@ const files = [ /** * Date */ - getPath('components', 'calendar', 'calendar'), - getPath('components', 'calendar', 'calendar-cell'), - getPath('components', 'calendar', 'calendar-grid'), - getPath('components', 'calendar', 'calendar-header'), - getPath('components', 'calendar', 'calendar-provider'), - getPath('components', 'calendar', 'calendar-title'), - getPath('components', 'date-field', 'date-field'), - getPath('components', 'date-picker', 'date-picker'), - getPath('components', 'date-range-picker', 'date-range-picker'), - getPath('components', 'date-segment', 'date-segment'), - getPath('components', 'range-calendar', 'range-calendar'), - getPath('components', 'time-input', 'time-input'), + getPath('shoreline', 'components', 'calendar', 'calendar'), + getPath('shoreline', 'components', 'calendar', 'calendar-cell'), + getPath('shoreline', 'components', 'calendar', 'calendar-grid'), + getPath('shoreline', 'components', 'calendar', 'calendar-header'), + getPath('shoreline', 'components', 'calendar', 'calendar-provider'), + getPath('shoreline', 'components', 'calendar', 'calendar-title'), + getPath('shoreline', 'components', 'date-field', 'date-field'), + getPath('shoreline', 'components', 'date-picker', 'date-picker'), + getPath('shoreline', 'components', 'date-range-picker', 'date-range-picker'), + getPath('shoreline', 'components', 'date-segment', 'date-segment'), + getPath('shoreline', 'components', 'range-calendar', 'range-calendar'), + getPath('shoreline', 'components', 'time-input', 'time-input'), + /** + * Charts + */ +] + +const chart = getPath('charts', 'components', 'chart', 'chart') +const chartVariants = [ + { + type: 'Bar', + description: 'teste', + }, ] let tsCode = ` @@ -174,6 +190,23 @@ async function main() { ` } }) + chartVariants.forEach((chartVariant) => { + const ref = getReferences(chart)[0] + if (ref) { + const displayName = chartVariant.type + const refName = `${ref?.name}-${chartVariant.type}` + const newRef = { + ...ref, + name: displayName, + description: chartVariant.description, + } + refs[kebabCase(refName)] = newRef + + tsCode += ` + "${kebabCase(refName)}": ${JSON.stringify(newRef)}, + ` + } + }) tsCode += '}' @@ -192,8 +225,8 @@ async function main() { }) } -function getPath(pkg, folder, file) { - return join(dirname(''), `../shoreline/src/${pkg}/${folder}/${file}.tsx`) +function getPath(pkg, path, folder, file) { + return join(dirname(''), `../${pkg}/src/${path}/${folder}/${file}.tsx`) } main() diff --git a/packages/docs/utils/all-components-list.ts b/packages/docs/utils/all-components-list.ts index 1a0c55b49b..35d2d9428a 100644 --- a/packages/docs/utils/all-components-list.ts +++ b/packages/docs/utils/all-components-list.ts @@ -55,3 +55,5 @@ export const allPrimitivesList = [ 'locale-provider', 'visually-hidden', ] + +export const allChartsList = ['bar'] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58eca376c9..2b7d6aac4e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -148,6 +148,37 @@ importers: specifier: 7.2.0 version: 7.2.0 + packages/charts: + dependencies: + '@vtex/shoreline-utils': + specifier: workspace:* + version: link:../utils + echarts-for-react: + specifier: ^3.0.2 + version: 3.0.2(echarts@5.5.0)(react@18.3.1) + lodash: + specifier: ^4.17.21 + version: 4.17.21 + react: + specifier: 18.x + version: 18.3.1 + react-dom: + specifier: 18.x + version: 18.3.1(react@18.3.1) + vitest-canvas-mock: + specifier: ^0.3.3 + version: 0.3.3(vitest@1.6.0(@types/node@22.7.8)(jsdom@23.0.0)(lightningcss@1.27.0)(terser@5.31.0)) + devDependencies: + '@types/lodash': + specifier: ^4.17.4 + version: 4.17.4 + '@vtex/shoreline': + specifier: workspace:* + version: link:../shoreline + echarts: + specifier: 5.5.0 + version: 5.5.0 + packages/css: dependencies: '@vtex/shoreline-utils': @@ -187,6 +218,9 @@ importers: '@vtex/shoreline': specifier: workspace:* version: link:../shoreline + '@vtex/shoreline-charts': + specifier: workspace:* + version: link:../charts '@vtex/shoreline-ts-table': specifier: workspace:* version: link:../ts-table @@ -4573,6 +4607,9 @@ packages: engines: {node: '>=4'} hasBin: true + cssfontparser@1.2.1: + resolution: {integrity: sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==} + cssstyle@3.0.0: resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} engines: {node: '>=14'} @@ -5006,6 +5043,15 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + echarts-for-react@3.0.2: + resolution: {integrity: sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==} + peerDependencies: + echarts: ^3.0.0 || ^4.0.0 || ^5.0.0 + react: ^15.0.0 || >=16.0.0 + + echarts@5.5.0: + resolution: {integrity: sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -6359,6 +6405,9 @@ packages: engines: {node: '>=10'} hasBin: true + jest-canvas-mock@2.5.2: + resolution: {integrity: sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==} + jest-changed-files@29.7.0: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7366,6 +7415,9 @@ packages: module-details-from-path@1.0.3: resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} + moo-color@1.0.3: + resolution: {integrity: sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -8810,6 +8862,9 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + size-sensor@1.0.2: + resolution: {integrity: sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -9311,6 +9366,9 @@ packages: tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} @@ -9732,6 +9790,11 @@ packages: terser: optional: true + vitest-canvas-mock@0.3.3: + resolution: {integrity: sha512-3P968tYBpqYyzzOaVtqnmYjqbe13576/fkjbDEJSfQAkHtC5/UjuRHOhFEN/ZV5HVZIkaROBUWgazDKJ+Ibw+Q==} + peerDependencies: + vitest: '*' + vitest@0.34.6: resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} engines: {node: '>=v14.18.0'} @@ -10098,6 +10161,9 @@ packages: zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + zrender@5.5.0: + resolution: {integrity: sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==} + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -14931,6 +14997,8 @@ snapshots: cssesc@3.0.0: {} + cssfontparser@1.2.1: {} + cssstyle@3.0.0: dependencies: rrweb-cssom: 0.6.0 @@ -15372,6 +15440,18 @@ snapshots: eastasianwidth@0.2.0: {} + echarts-for-react@3.0.2(echarts@5.5.0)(react@18.3.1): + dependencies: + echarts: 5.5.0 + fast-deep-equal: 3.1.3 + react: 18.3.1 + size-sensor: 1.0.2 + + echarts@5.5.0: + dependencies: + tslib: 2.3.0 + zrender: 5.5.0 + ee-first@1.1.1: {} ejs@3.1.10: @@ -17040,6 +17120,11 @@ snapshots: filelist: 1.0.4 minimatch: 3.1.2 + jest-canvas-mock@2.5.2: + dependencies: + cssfontparser: 1.2.1 + moo-color: 1.0.3 + jest-changed-files@29.7.0: dependencies: execa: 5.1.1 @@ -18664,6 +18749,10 @@ snapshots: module-details-from-path@1.0.3: {} + moo-color@1.0.3: + dependencies: + color-name: 1.1.4 + ms@2.0.0: {} ms@2.1.2: {} @@ -20491,6 +20580,8 @@ snapshots: sisteransi@1.0.5: {} + size-sensor@1.0.2: {} + slash@3.0.0: {} slash@4.0.0: {} @@ -20980,6 +21071,8 @@ snapshots: tslib@1.14.1: {} + tslib@2.3.0: {} + tslib@2.6.3: {} tsup@8.1.0(@swc/core@1.5.24(@swc/helpers@0.5.13))(postcss@8.4.38)(typescript@5.5.2): @@ -21380,6 +21473,24 @@ snapshots: - supports-color - terser + vite-node@1.6.0(@types/node@22.7.8)(lightningcss@1.27.0)(terser@5.31.0): + dependencies: + cac: 6.7.14 + debug: 4.3.5 + pathe: 1.1.2 + picocolors: 1.0.1 + vite: 5.4.9(@types/node@22.7.8)(lightningcss@1.27.0)(terser@5.31.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite@5.0.13(@types/node@20.14.9)(lightningcss@1.27.0)(terser@5.31.0): dependencies: esbuild: 0.19.12 @@ -21402,6 +21513,22 @@ snapshots: lightningcss: 1.27.0 terser: 5.31.0 + vite@5.4.9(@types/node@22.7.8)(lightningcss@1.27.0)(terser@5.31.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.47 + rollup: 4.24.0 + optionalDependencies: + '@types/node': 22.7.8 + fsevents: 2.3.3 + lightningcss: 1.27.0 + terser: 5.31.0 + + vitest-canvas-mock@0.3.3(vitest@1.6.0(@types/node@22.7.8)(jsdom@23.0.0)(lightningcss@1.27.0)(terser@5.31.0)): + dependencies: + jest-canvas-mock: 2.5.2 + vitest: 1.6.0(@types/node@22.7.8)(jsdom@23.0.0)(lightningcss@1.27.0)(terser@5.31.0) + vitest@0.34.6(jsdom@23.0.0)(lightningcss@1.27.0)(playwright@1.44.1)(terser@5.31.0): dependencies: '@types/chai': 4.3.16 @@ -21476,6 +21603,41 @@ snapshots: - supports-color - terser + vitest@1.6.0(@types/node@22.7.8)(jsdom@23.0.0)(lightningcss@1.27.0)(terser@5.31.0): + dependencies: + '@vitest/expect': 1.6.0 + '@vitest/runner': 1.6.0 + '@vitest/snapshot': 1.6.0 + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + acorn-walk: 8.3.2 + chai: 4.4.1 + debug: 4.3.5 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.10 + pathe: 1.1.2 + picocolors: 1.0.1 + std-env: 3.7.0 + strip-literal: 2.1.0 + tinybench: 2.8.0 + tinypool: 0.8.4 + vite: 5.4.9(@types/node@22.7.8)(lightningcss@1.27.0)(terser@5.31.0) + vite-node: 1.6.0(@types/node@22.7.8)(lightningcss@1.27.0)(terser@5.31.0) + why-is-node-running: 2.2.2 + optionalDependencies: + '@types/node': 22.7.8 + jsdom: 23.0.0 + transitivePeerDependencies: + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vorpal@1.12.0: dependencies: babel-polyfill: 6.26.0 @@ -21828,4 +21990,8 @@ snapshots: zod@3.23.8: {} + zrender@5.5.0: + dependencies: + tslib: 2.3.0 + zwitch@2.0.4: {} diff --git a/vite.config.ts b/vite.config.ts index 067a326da3..cd417b333b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -18,7 +18,13 @@ export default defineConfig({ '**/.{idea,git,cache,output,temp}/**', '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*', ], - setupFiles: ['./packages/test-utils/dist/setup.mjs'], + setupFiles: [ + './packages/test-utils/dist/setup.mjs', + './packages/charts/src/tests/vitest.config.ts', + ], + deps: { + inline: ['vitest-canvas-mock'], + }, environment: 'jsdom', css: false, },