Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b430618
Move footnote before sources
sakari-malkki Sep 19, 2025
f7ab67b
Snapshot test to cover footnote and source
sakari-malkki Sep 19, 2025
701335f
Increment patch version number
sakari-malkki Sep 19, 2025
3602cc7
Add table with footnote and source story for storybook
sakari-malkki Sep 22, 2025
498d413
Show table source by default
sakari-malkki Sep 22, 2025
1506a68
Merge pull request #118 from StatisticsFinland/feature/source-after-f…
sakari-malkki Sep 24, 2025
e319cef
Show title by default for tables. Allow hiding for charts
sakari-malkki Sep 19, 2025
0157dac
Renames showTableTitles to showTitles
sakari-malkki Sep 24, 2025
c84a9bd
Added changelog to describe breaking changes
sakari-malkki Sep 24, 2025
f75fbb1
Readme fix
sakari-malkki Sep 25, 2025
feb7cd0
Fix merge conflicts
sakari-malkki Sep 25, 2025
823b3c4
Update test snapshot after rebase
sakari-malkki Sep 25, 2025
aa4317b
Merge pull request #117 from StatisticsFinland/feature/show-table-title
sakari-malkki Sep 25, 2025
06c792e
Updates highcharts and fixes export in burgermenu
sakari-malkki Sep 30, 2025
d2b993a
Merge pull request #120 from StatisticsFinland/feature/highcharts-update
sakari-malkki Sep 30, 2025
11a78cd
Moves highcharts back to dependencies from devdeps
sakari-malkki Sep 30, 2025
f19d58c
Merge pull request #121 from StatisticsFinland/feature/highcharts-update
sakari-malkki Sep 30, 2025
510025f
Merge pull request #119 from StatisticsFinland/dev
sakari-malkki Oct 1, 2025
0c2016f
Disable html from exports
sakari-malkki Oct 6, 2025
ce9601c
Explicitly set export font family. Support for custom font family
sakari-malkki Oct 7, 2025
f1e04b0
Minor and patch updates
sakari-malkki Oct 7, 2025
c66b98b
Update jest
sakari-malkki Oct 7, 2025
5845d40
Update uuid
sakari-malkki Oct 7, 2025
f9e3f49
Update jest jsdom
sakari-malkki Oct 7, 2025
0cb44be
Update types/jest
sakari-malkki Oct 7, 2025
46acb71
Update storybook where applicable
sakari-malkki Oct 7, 2025
c524493
Merge pull request #122 from StatisticsFinland/feature/dependency-upd…
sakari-malkki Oct 17, 2025
3c277de
Merge pull request #123 from StatisticsFinland/bugfix/disable-export-…
sakari-malkki Oct 21, 2025
0cea0e2
Merge pull request #124 from StatisticsFinland/dev
sakari-malkki Oct 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
v1.3.0 (24 September 2025):
- <Chart> component optional property 'showTableTitles' renamed to 'showTitles' as it now applies to both chart and table titles. Default value is true.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ drawChart(container, pxGraphData, locale);>
- showContextMenu: boolean - Flag to show or hide the context menu in the visualization.
- menuItemDefinitions: object[] - Definitions for custom context menu items. These can be either links or run custom functions. The provided object must implement either the IFunctionalMenuItem or ILinkMenuItem interface.
- menuIconInheritColor: boolean - Flag to inherit the color of the context menu icons from the parent element.
- showTableTitles: boolean - Flag to show or hide the titles in the table view.
- showTitles: boolean - Flag to show or hide the titles in the tables and charts.
- showTableUnits: boolean - Flag to show or hide the units in the table view.
- showTableSources: boolean - Flag to show or hide the sources in the table view.
- footnote: string - Custom footnote to be displayed in the visualization.
Expand Down
6,109 changes: 3,741 additions & 2,368 deletions package-lock.json

Large diffs are not rendered by default.

38 changes: 18 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@statisticsfinland/pxvisualizer",
"version": "1.2.4",
"version": "1.3.2",
"description": "Component library for visualizing PxGraf data",
"main": "./dist/pxv.cjs",
"jestSonar": {
Expand Down Expand Up @@ -46,32 +46,30 @@
"author": "Statistics Finland",
"license": "Apache-2.0",
"devDependencies": {
"@babel/core": "^7.26.7",
"@storybook/addon-a11y": "^8.5.3",
"@storybook/addon-actions": "^8.1.3",
"@storybook/addon-essentials": "^8.5.3",
"@storybook/addon-interactions": "^8.5.3",
"@storybook/addon-links": "^8.5.3",
"@babel/core": "^7.28.4",
"@storybook/addon-a11y": "^8.6.14",
"@storybook/addon-actions": "^8.6.14",
"@storybook/addon-essentials": "^8.6.14",
"@storybook/addon-interactions": "^8.6.14",
"@storybook/addon-links": "^8.6.14",
"@storybook/addon-webpack5-compiler-swc": "^3.0.0",
"@storybook/blocks": "^8.1.3",
"@storybook/react": "^8.1.3",
"@storybook/react-webpack5": "^8.5.3",
"@storybook/test": "^8.1.3",
"@storybook/blocks": "^8.6.14",
"@storybook/react": "^8.6.14",
"@storybook/react-webpack5": "^8.6.14",
"@storybook/test": "^8.6.14",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.3.0",
"@types/file-saver": "^2.0.7",
"@types/jest": "^29.5.14",
"@types/jest": "^30.0.0",
"@types/papaparse": "^5.3.15",
"@types/react": "^19.1.0",
"@types/styled-components": "^5.1.34",
"@types/uuid": "^10.0.0",
"babel-loader": "^10.0.0",
"clean-publish": "^5.1.0",
"decimal.js": "^10.5.0",
"highcharts": "^12.1.2",
"highcharts-react-official": "^3.2.1",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest": "^30.2.0",
"jest-environment-jsdom": "^30.2.0",
"jest-junit": "^16.0.0",
"jest-sonar-reporter": "^2.0.0",
"jest-styled-components": "^7.2.0",
Expand All @@ -80,18 +78,18 @@
"react": "^19.1.0",
"react-dom": "^19.1.0",
"semver": "^7.7.0",
"storybook": "^8.5.3",
"storybook": "^8.6.14",
"styled-components": "^6.1.17",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"typescript": "^5.8.3",
"uuid": "^11.0.5"
"uuid": "^13.0.0"
},
"dependencies": {
"decimal.js": "^10.5.0",
"fflate": "^0.8.2",
"highcharts": "^12.1.2",
"highcharts-react-official": "^3.2.1"
"highcharts": "^12.4.0",
"highcharts-react-official": "^3.2.2"
},
"peerDependencies": {
"react": "^18.2.0 || ^19.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/core/chartOptions/basicHorizontalBarchartOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { IChartOptions } from '../types/chartOptions';

export const basicHorizontalBarChartOptions = (view: View, locale: string, options?: IChartOptions): Options => {
return {
...commonHorizontalBarChartOptions(view, locale),
...commonHorizontalBarChartOptions(view, locale, options),
series: buildBarChartSeries(view, locale, false, options?.accessibilityMode),
chart: { type: 'bar', spacingBottom: 60 },
yAxis: {
Expand Down
19 changes: 10 additions & 9 deletions src/core/chartOptions/chartOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import { getLinearAxisTickPositionerFunction } from './Utility/tickPositioners';
import { IChartOptions } from '../types/chartOptions';
import { buildBarChartSeries, buildColumnChartSeries } from './Utility/seriesDataBuilder';

export const commonChartOptions = (view: View, locale: string): Options => {
export const commonChartOptions = (view: View, locale: string, options?: IChartOptions): Options => {
const showTitle: boolean = options?.showTitle ?? true;
return {
accessibility: {
point: {
descriptionFormatter: getScreenReaderFormatterCallbackFunction(view, locale)
}
},
title: { text: view.header[locale] },
title: { text: showTitle ? view.header[locale] : undefined },
subtitle: { text: view.subheaderValues.map(sv => sv[locale]).join(' | ') },
credits: { text: `${Translations.source[locale]}: ${view.sources.map(s => s[locale]).join(', ')}` },
tooltip: {
Expand Down Expand Up @@ -65,9 +66,9 @@ export const commonBasicHorizontalBarChartYAxisOptions = (view: View, locale: st
return yAxisOptions;
}

export const commonHorizontalBarChartOptions = (view: View, locale: string): Options => {
export const commonHorizontalBarChartOptions = (view: View, locale: string, options?: IChartOptions): Options => {
return {
...commonChartOptions(view, locale),
...commonChartOptions(view, locale, options),
chart: { type: 'bar' },
xAxis: {
categories: view.columnNameGroups.map(cng => cng.map(n => n[locale]).join(', ')),
Expand All @@ -83,7 +84,7 @@ export const commonHorizontalBarChartOptions = (view: View, locale: string): Opt

export const commonStackedHorizontalBarChartOptions = (view: View, locale: string, options?: IChartOptions): Options => {
return {
...commonHorizontalBarChartOptions(view, locale),
...commonHorizontalBarChartOptions(view, locale, options),
series: buildBarChartSeries(view, locale, true, options?.accessibilityMode),
legend: {
...commonLegendStyleOptions,
Expand All @@ -95,9 +96,9 @@ export const commonStackedHorizontalBarChartOptions = (view: View, locale: strin
};
}

export const commonVerticalBarChartOptions = (view: View, locale: string): Options => {
export const commonVerticalBarChartOptions = (view: View, locale: string, options?: IChartOptions): Options => {
const result = {
...commonChartOptions(view, locale),
...commonChartOptions(view, locale, options),
chart: { type: 'column' },
xAxis: getXAxisOptions(view, locale),
};
Expand All @@ -106,7 +107,7 @@ export const commonVerticalBarChartOptions = (view: View, locale: string): Optio

export const commonBasicVerticalBarChartOptions = (view: View, locale: string, options?: IChartOptions): Options => {
return {
...commonVerticalBarChartOptions(view, locale),
...commonVerticalBarChartOptions(view, locale, options),
series: buildColumnChartSeries(view, locale, false, options?.accessibilityMode),
yAxis: {
softMin: 0,
Expand All @@ -120,7 +121,7 @@ export const commonBasicVerticalBarChartOptions = (view: View, locale: string, o

export const commonStackedVerticalBarChartOptions = (view: View, locale: string, options?: IChartOptions): Options => {
return {
...commonVerticalBarChartOptions(view, locale),
...commonVerticalBarChartOptions(view, locale, options),
series: buildColumnChartSeries(view, locale, true, options?.accessibilityMode),
legend: {
...commonLegendStyleOptions,
Expand Down
2 changes: 1 addition & 1 deletion src/core/chartOptions/groupHorizontalBarChartOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { IChartOptions } from '../types/chartOptions';

export const groupHorizontalBarChartOptions = (view: View, locale: string, options?: IChartOptions): Options => {
return {
...commonHorizontalBarChartOptions(view, locale),
...commonHorizontalBarChartOptions(view, locale, options),
series: buildBarChartSeries(view, locale, false, options?.accessibilityMode),
yAxis: {
...commonBasicHorizontalBarChartYAxisOptions(view, locale),
Expand Down
2 changes: 1 addition & 1 deletion src/core/chartOptions/lineChartOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const lineChartOptions = (view: View, locale: string, options?: IChartOpt
const cutValueAxis = !view.visualizationSettings?.cutValueAxis ? 0 : undefined;
const markerSettings = options?.accessibilityMode ? { enabledThreshold: 3 } : { enabled: false };
return {
...commonChartOptions(view, locale),
...commonChartOptions(view, locale, options),
chart: { type: 'line' },
tooltip: {
formatter: getLineChartToolTipFormatterFunction(view, locale)
Expand Down
2 changes: 1 addition & 1 deletion src/core/chartOptions/pyramidChartOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const pyramidChartOptions = (view: View, locale: string, options?: IChart
const categories = view.columnNameGroups.map(cng => cng.map(n => n[locale]).join(', '));
const maxValue = Math.max(...view.series.map(s => Math.max(...s.series.map(dataCell => dataCell.value ?? 0))));
return {
...commonChartOptions(view, locale),
...commonChartOptions(view, locale, options),
chart: { type: 'bar' },
xAxis: {
categories: categories,
Expand Down
5 changes: 3 additions & 2 deletions src/core/chartOptions/scatterPlotOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { Options } from 'highcharts';
import { IDataSeries, View } from "../types/view";
import { getScatterPlotTooltipFormatterFunction } from './Utility/formatters';
import { commonChartOptions, commonYAxisOptions } from './chartOptions';
import { IChartOptions } from '../types/chartOptions';

export const scatterPlotOptions = (view: View, locale: string): Options => {
export const scatterPlotOptions = (view: View, locale: string, options?: IChartOptions): Options => {
const X_INDEX = 1; const Y_INDEX = 0;
const cutValueAxis = !view.visualizationSettings?.cutValueAxis ? 0 : undefined;
return {
...commonChartOptions(view, locale),
...commonChartOptions(view, locale, options),
chart: { type: 'scatter' },
xAxis: {
softMin: 0,
Expand Down
2 changes: 1 addition & 1 deletion src/core/conversion/pxGrafDataConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const convertPxGraphDataToChartOptions = (locale: string, view: View, opt
case EVisualizationType.PyramidChart:
return pyramidChartOptions(view, locale, options);
case EVisualizationType.ScatterPlot:
return scatterPlotOptions(view, locale);
return scatterPlotOptions(view, locale, options);
default:
throw new Error('Unsupported chart type');
}
Expand Down
9 changes: 4 additions & 5 deletions src/core/conversion/viewUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ import {
import { SELECTABLE_TABLE_WITH_MISSING_DATA } from './fixtures/tableChart';
import { ASCENDING, DESCENDING, SUM, REVERSED, NO_SORTING } from './viewSorting';
import { buildSeries, convertPxGrafResponseToView, convertToRelative } from './viewUtils';
import { v4 as uuidV4 } from 'uuid'

const createContentComponent = (overrides?: Partial<IContentComponent>) => {
const id = uuidV4();
const id = Math.random().toString(36).substring(2, 15);
const defaultContentComponent = {
unit: { fi: `test-unit-${id}` },
source: { fi: `test-source-${id}` },
Expand All @@ -31,7 +30,7 @@ const createContentComponent = (overrides?: Partial<IContentComponent>) => {
};

const createVariableValue = (overrides?: Partial<IVariableValueMeta>) => {
const id = uuidV4();
const id = Math.random().toString(36).substring(2, 15);
const defaultValueMeta = {
name: { fi: `test-variable-value-name-${id}` },
code: `test-variable-value-code-${id}`,
Expand All @@ -46,7 +45,7 @@ const createVariableValue = (overrides?: Partial<IVariableValueMeta>) => {
};

const createVariable = (overrides?: Partial<IVariableMeta>): IVariableMeta => {
const id = uuidV4();
const id = Math.random().toString(36).substring(2, 15);
const defaultVariableMeta: IVariableMeta = {
code: `test-variable-code-${id}`,
name: { fi: `test-variable-name-${id}` },
Expand All @@ -59,7 +58,7 @@ const createVariable = (overrides?: Partial<IVariableMeta>): IVariableMeta => {
};

const createPxGrafResponse = (overrides?: Partial<IQueryVisualizationResponse>): IQueryVisualizationResponse => {
const id = uuidV4();
const id = Math.random().toString(36).substring(2, 15);
const defaultMetaData: IQueryVisualizationResponse = {
tableReference: { name: `test-table-reference-${id}`, hierarchy: [] },
data: [],
Expand Down
2 changes: 1 addition & 1 deletion src/core/highcharts/drawChart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const drawChart = (
{
loadHighchartsModules();
const validLocale = formatLocale(locale);
Highcharts.setOptions(defaultTheme(validLocale));
Highcharts.setOptions(defaultTheme(validLocale, options?.fontFamily));
const variableSelections = extractSelectableVariableValues(pxGraphData.selectableVariableCodes, pxGraphData.metaData, pxGraphData.visualizationSettings.defaultSelectableVariableCodes, selectedVariableCodes);
const view = convertPxGrafResponseToView(pxGraphData, variableSelections);
const highChartOptions = convertPxGraphDataToChartOptions(validLocale, view, options);
Expand Down
15 changes: 12 additions & 3 deletions src/core/highcharts/themes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getAxisLabelFormatterFunction } from "../chartOptions/Utility/formatter
import { Translations, ArrayTranslations } from "../conversion/translations";
import { defaultColors } from "./defaultColors";

export const defaultTheme: (locale: string) => Highcharts.Options = (locale) => ({
export const defaultTheme: (locale: string, fontFamily?: string) => Highcharts.Options = (locale, fontFamily) => ({
accessibility: {
keyboardNavigation: {
seriesNavigation: {
Expand All @@ -27,7 +27,16 @@ export const defaultTheme: (locale: string) => Highcharts.Options = (locale) =>
exporting: {
enabled: false,
fallbackToExportServer: false,
allowHTML: true,
allowHTML: false,
chartOptions: {
// Setting fontFamily prevents Highcharts 12.4+ from inlining web fonts in SVG exports,
// which was causing extremely large file sizes (1000x larger than before)
chart: {
style: {
fontFamily: fontFamily || '"Barlow Semi Condensed", Verdana, sans-serif'
} as any // Type assertion to work around Highcharts typing limitation
}
}
},
lang: {
accessibility: {
Expand Down Expand Up @@ -106,7 +115,7 @@ export const defaultTheme: (locale: string) => Highcharts.Options = (locale) =>
colors: defaultColors, // chart series default colors
chart: {
style: {
fontFamily: '"Barlow Semi Condensed", Verdana, sans-serif'
fontFamily: fontFamily ?? '"Barlow Semi Condensed", Verdana, sans-serif'
},
spacingBottom: 30,
spacingLeft: 20, // for tilted labels to fit in the x axis with ellipsis overflow
Expand Down
34 changes: 33 additions & 1 deletion src/core/tables/__snapshots__/htmlTable.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`Html table render tests should match snapshot: Table with column variables only 1`] = `
"<div
Expand Down Expand Up @@ -3542,3 +3542,35 @@ exports[`Html table render tests should match snapshot: Table with row variables
</p>
</div>"
`;

exports[`Html table render tests should match snapshot: Table with source and footnote 1`] = `
"<div
id="test-6895638450983059889"
>
<table
tabindex="0"
>
<caption
class="tableChart-caption"
>
Lukumäärä, Vantaa, Yksiöt, Vapaarahoitteinen 2022Q4
</caption>
<tbody>
<tr>
<td>
2 548
</td>
</tr>
</tbody>
</table>
<p>
Yksikkö: lukumäärä
</p>
<p>
Test footnote
</p>
<p>
Lähde: PxVisualizer-fi
</p>
</div>"
`;
23 changes: 23 additions & 0 deletions src/core/tables/htmlTable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,29 @@ describe('Html table render tests', () => {
document.body.removeChild(div);
});

it('should match snapshot: Table with source and footnote', () => {
const mockVarSelections = extractSelectableVariableValues(
TABLE_WITH_ONE_CELL.pxGraphData.selectableVariableCodes,
TABLE_WITH_ONE_CELL.pxGraphData.metaData,
TABLE_WITH_ONE_CELL.pxGraphData.visualizationSettings.defaultSelectableVariableCodes,
TABLE_WITH_ONE_CELL.selectedVariableCodes);
const mockView = convertPxGrafResponseToView(TABLE_WITH_ONE_CELL.pxGraphData, mockVarSelections);
const locale = 'fi';

const testId = 'test-6895638450983059889';

const div = document.createElement('div');
div.id = testId;
document.body.appendChild(div);

renderHtmlTable(mockView, locale, true, true, true, testId, 'Test footnote');

const renderedOutput = prettyDOM(div);
expect(renderedOutput).toMatchSnapshot();

document.body.removeChild(div);
});

it('should match snapshot: Table with missing data and selectable values', () => {
const mockVarSelections = extractSelectableVariableValues(
SELECTABLE_TABLE_WITH_MISSING_DATA.selectableVariableCodes,
Expand Down
Loading