Skip to content

Commit

Permalink
Charts: Adding Rollup (#40817)
Browse files Browse the repository at this point in the history
* Charts: Adding Rollup config

* changelog

* Charts: Removing tsup

* Charts: Fixing tsconfig
  • Loading branch information
grzegorz-cp authored Jan 2, 2025
1 parent bccd521 commit 3947e3c
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 645 deletions.
652 changes: 72 additions & 580 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions projects/js-packages/charts/changelog/add-charts-rollup
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

Switching esbuild to rollup for better treeshaking.
43 changes: 32 additions & 11 deletions projects/js-packages/charts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
"test-coverage": "pnpm run test --coverage",
"storybook": "cd ../storybook && pnpm run storybook:dev",
"compile-ts": "tsc --pretty",
"build": "pnpm run clean-build && pnpm run compile-ts",
"build:prod": "tsup src/index.ts --minify --dts",
"build": "rollup -c",
"build:prod": "rollup -c --environment NODE_ENV:production",
"build:dev": "rollup -c --environment NODE_ENV:development",
"build:watch": "rollup -c -w",
"clean-build": "rm -rf dist/"
},
"dependencies": {
Expand All @@ -36,25 +38,33 @@
"@visx/text": "3.12.0",
"@visx/tooltip": "^3.8.0",
"@visx/xychart": "3.12.0",
"clsx": "2.1.1"
"clsx": "2.1.1",
"tslib": "2.5.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "26.0.1",
"@rollup/plugin-json": "6.1.0",
"@rollup/plugin-node-resolve": "15.3.0",
"@rollup/plugin-terser": "0.4.3",
"@rollup/plugin-typescript": "12.1.0",
"@storybook/blocks": "8.4.6",
"@storybook/react": "8.4.6",
"@types/react": "18.3.18",
"@types/react-dom": "18.3.5",
"esbuild": "0.24.2",
"esbuild-sass-plugin": "3.3.1",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"jest-extended": "4.0.2",
"postcss": "8.4.47",
"postcss-modules": "6.0.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"rollup": "3.29.5",
"rollup-plugin-dts": "6.1.1",
"rollup-plugin-peer-deps-external": "2.2.4",
"rollup-plugin-postcss": "4.0.2",
"sass": "1.64.1",
"sass-embedded": "1.83.0",
"storybook": "8.4.6",
"tsup": "8.3.5",
"typescript": "5.7.2"
},
"peerDependencies": {
Expand All @@ -63,11 +73,22 @@
},
"exports": {
".": {
"jetpack:src": "./src/index.ts",
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./components/*": {
"import": "./dist/components/*/index.js",
"require": "./dist/components/*/index.cjs.js",
"types": "./dist/components/*/index.d.ts"
},
"./style.css": "./dist/style.css"
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts"
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"sideEffects": [
"*.css",
"*.scss"
]
}
142 changes: 142 additions & 0 deletions projects/js-packages/charts/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Import necessary plugins for building the library
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import resolve from '@rollup/plugin-node-resolve';
import terser from '@rollup/plugin-terser';
import typescript from '@rollup/plugin-typescript';
import { defineConfig } from 'rollup';
import dts from 'rollup-plugin-dts';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';

// Common plugins used across all build configurations
const commonPlugins = [
// Automatically externalize peer dependencies
peerDepsExternal( {
includeDependencies: true,
} ),
// Locate and bundle third-party dependencies from node_modules
resolve( {
preferBuiltins: true,
extensions: [ '.tsx', '.ts', '.js', '.jsx' ],
} ),
// Convert CommonJS modules to ES6
commonjs(),
// Allow importing JSON files
json(),
// Process SCSS/CSS modules
postcss( {
// Configure CSS modules with scoped names
modules: {
generateScopedName: '[name]__[local]__[hash:base64:5]',
},
extract: 'style.css',
autoModules: false,
use: [ 'sass' ],
} ),
];

// Main bundle configuration for the entire library
const mainConfig = {
// Entry point for the bundle
input: 'src/index.ts',
// Output configuration for different module formats
output: [
{
file: './dist/index.js',
format: 'cjs', // CommonJS format for Node.js
sourcemap: true,
sourcemapPathTransform: relativeSourcePath => {
return `/@automattic/charts/${ relativeSourcePath }`;
},
},
{
file: './dist/index.mjs',
format: 'esm', // ES modules for modern bundlers
sourcemap: true,
},
],
// Mark all dependencies as external to avoid bundling them
external: [ 'react', 'react-dom', /^@visx\/.*/, '@react-spring/web', 'clsx', 'tslib' ],
plugins: [
...commonPlugins,
// TypeScript compilation
typescript( {
tsconfig: './tsconfig.json',
declaration: false, // Declarations handled by dts plugin
sourceMap: true,
compilerOptions: {
verbatimModuleSyntax: true,
},
} ),
terser(),
],
// Handle circular dependencies warning
onwarn( warning, warn ) {
if ( warning.code === 'CIRCULAR_DEPENDENCY' ) {
return;
}
warn( warning );
},
};

// List of components to build individually
const components = [
'components/bar-chart',
'components/line-chart',
'components/pie-chart',
'components/pie-semi-circle-chart',
'components/tooltip',
'components/legend',
'components/grid-control',
'providers/theme',
];

// Generate individual bundles for each component
const componentConfigs = components.map( component => ( {
// Component entry point - try both .tsx and .ts extensions
input: `src/${ component }/index`,
// Output both ESM and CJS formats
output: [
{
file: `dist/${ component }/index.js`,
format: 'esm',
sourcemap: true,
},
{
file: `dist/${ component }/index.cjs.js`,
format: 'cjs',
sourcemap: true,
},
],
// Same external config as main bundle
external: [ 'react', 'react-dom', /^@visx\/.*/, '@react-spring/web', 'clsx', 'tslib' ],
plugins: [
...commonPlugins,
typescript( {
tsconfig: './tsconfig.json',
declaration: false,
sourceMap: true,
compilerOptions: {
verbatimModuleSyntax: true,
},
} ),
terser(),
],
} ) );

// Configuration for generating TypeScript declaration files
const typesConfig = {
input: 'src/index.ts',
output: [ { file: 'dist/index.d.ts', format: 'es' } ],
plugins: [
dts( {
respectExternal: true,
} ),
],
// Don't include style imports in type definitions
external: [ /\.scss$/, /\.css$/, 'react', '@types/react' ],
};

// Export all configurations to be built in parallel
export default defineConfig( [ mainConfig, ...componentConfigs, typesConfig ] );
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ type BarChartTooltipData = { value: number; xLabel: string; yLabel: string; seri

const BarChart: FC< BarChartProps > = ( {
data,
width,
height,
width = 500, //TODO: replace when making the components responsive
height = 500, //TODO: replace when making the components responsive
margin = { top: 20, right: 20, bottom: 40, left: 40 },
withTooltips = false,
showLegend = false,
Expand Down Expand Up @@ -65,7 +65,7 @@ const BarChart: FC< BarChartProps > = ( {
const yMax = height - margins.top - margins.bottom;

// Get labels for x-axis from the first series (assuming all series have same labels)
const labels = data[ 0 ].data?.map( d => d?.label );
const labels = data[ 0 ].data?.map( d => d?.label || '' );

// Create scales
const xScale = scaleBand< string >( {
Expand Down Expand Up @@ -109,14 +109,14 @@ const BarChart: FC< BarChartProps > = ( {
{ data.map( ( series, seriesIndex ) => (
<Group key={ seriesIndex }>
{ series.data.map( d => {
const xPos = xScale( d.label );
const xPos = xScale( d?.label || '' );
if ( xPos === undefined ) return null;

const barWidth = innerScale.bandwidth();
const barX = xPos + ( innerScale( seriesIndex.toString() ) ?? 0 );

const handleBarMouseMove = event =>
handleMouseMove( event, d.value, d.label, series.label, seriesIndex );
const handleBarMouseMove = ( event: MouseEvent< SVGRectElement > ) =>
handleMouseMove( event, d.value, d?.label || '', series.label, seriesIndex );

return (
<Bar
Expand All @@ -139,7 +139,7 @@ const BarChart: FC< BarChartProps > = ( {
</svg>

{ withTooltips && tooltipOpen && tooltipData && (
<BaseTooltip top={ tooltipTop } left={ tooltipLeft }>
<BaseTooltip top={ tooltipTop || 0 } left={ tooltipLeft || 0 }>
<div>
<div>{ tooltipData.yLabel }</div>
<div>
Expand Down
22 changes: 12 additions & 10 deletions projects/js-packages/charts/src/components/pie-chart/pie-chart.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Group } from '@visx/group';
import { Pie } from '@visx/shape';
import clsx from 'clsx';
import { SVGProps } from 'react';
import { SVGProps, type MouseEvent } from 'react';
import useChartMouseHandler from '../../hooks/use-chart-mouse-handler';
import { useChartTheme, defaultTheme } from '../../providers/theme';
import { Legend } from '../legend';
import { BaseTooltip } from '../tooltip';
import styles from './pie-chart.module.scss';
import type { BaseChartProps, DataPoint } from '../shared/types';
import type { BaseChartProps, DataPointPercentage } from '../shared/types';
import type { PieArcDatum } from '@visx/shape/lib/shapes/Pie';

// TODO: add animation

interface PieChartProps extends BaseChartProps< DataPoint[] > {
interface PieChartProps extends BaseChartProps< DataPointPercentage[] > {
/**
* Inner radius in pixels. If > 0, creates a donut chart. Defaults to 0.
*/
Expand All @@ -26,8 +27,8 @@ interface PieChartProps extends BaseChartProps< DataPoint[] > {
*/
const PieChart = ( {
data,
width,
height,
width = 500, //TODO: replace when making the components responsive
height = 500, //TODO: replace when making the components responsive
withTooltips = false,
innerRadius = 0,
className,
Expand All @@ -46,9 +47,9 @@ const PieChart = ( {
const centerY = height / 2;

const accessors = {
value: d => d.value,
value: ( d: PieArcDatum< DataPointPercentage > ) => d.value,
// Use the color property from the data object as a last resort. The theme provides colours by default.
fill: d => d.color || providerTheme.colors[ d.index ],
fill: ( d: PieArcDatum< DataPointPercentage > ) => d?.color || providerTheme.colors[ d.index ],
};

// Create legend items from data
Expand All @@ -72,7 +73,8 @@ const PieChart = ( {
return pie.arcs.map( ( arc, index ) => {
const [ centroidX, centroidY ] = pie.path.centroid( arc );
const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.25;
const handleMouseMove = event => onMouseMove( event, arc.data );
const handleMouseMove = ( event: MouseEvent< SVGElement > ) =>
onMouseMove( event, arc.data );

const pathProps: SVGProps< SVGPathElement > = {
d: pie.path( arc ) || '',
Expand Down Expand Up @@ -121,8 +123,8 @@ const PieChart = ( {
{ withTooltips && tooltipOpen && tooltipData && (
<BaseTooltip
data={ tooltipData }
top={ tooltipTop }
left={ tooltipLeft }
top={ tooltipTop || 0 }
left={ tooltipLeft || 0 }
style={ {
transform: 'translate(-50%, -100%)',
} }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { localPoint } from '@visx/event';
import { Group } from '@visx/group';
import Pie, { PieArcDatum } from '@visx/shape/lib/shapes/Pie';
import Pie, { type PieArcDatum } from '@visx/shape/lib/shapes/Pie';
import { Text } from '@visx/text';
import { useTooltip } from '@visx/tooltip';
import clsx from 'clsx';
Expand Down Expand Up @@ -35,7 +35,7 @@ type ArcData = PieArcDatum< DataPointPercentage >;

const PieSemiCircleChart: FC< PieSemiCircleChartProps > = ( {
data,
width,
width = 500, //TODO: replace when making the components responsive
label,
note,
className,
Expand Down Expand Up @@ -168,8 +168,8 @@ const PieSemiCircleChart: FC< PieSemiCircleChartProps > = ( {
value: tooltipData.value,
valueDisplay: tooltipData.valueDisplay,
} }
top={ tooltipTop }
left={ tooltipLeft }
top={ tooltipTop || 0 }
left={ tooltipLeft || 0 }
/>
) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const BaseTooltip = ( {
}: BaseTooltipProps ) => {
return (
<div className={ styles.tooltip } style={ { top, left } } role="tooltip">
{ children || <Component data={ data } className={ className } /> }
{ children || ( data && <Component data={ data } className={ className } /> ) }
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const useChartMouseHandler = ( {
onMouseMove,
onMouseLeave,
tooltipOpen,
tooltipData,
tooltipData: tooltipData || null,
tooltipLeft,
tooltipTop,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useContext, FC, ReactNode } from 'react';
import { createContext, useContext, FC, type ReactNode } from 'react';
import { defaultTheme } from './themes';
import type { ChartTheme } from '../../components/shared/types';

Expand Down
Loading

0 comments on commit 3947e3c

Please sign in to comment.