Guide

Chart Builder 3.10.0 — Release Notes

Release: Chart Builder 3.10.0 · PRC Platform 1.8 Work period: May – June 2026 Scope: prc-chart-builder, prc-charting-library Tracking: PRC-17 · PRC-402


Overview

Chart Builder 3.10.0 is a runtime-architecture and animation release. Three major initiatives ship together:

  1. Preact frontend + Script Module (PRC-17) — the chart frontend now loads as a native WordPress Script Module. @prc/charting-library ships a Preact bundle for the browser and keeps its existing React bundle for the editor. Reactive chart state and a programmatic action surface power the changes below.
  2. Animation suite (PRC-17) — opt-in entry animations across every major chart family (bars, lines, areas, dot plots, pies) with author-controlled easing, duration, stagger, and reduced-motion awareness.
  3. Bug fixes and chart action improvements (PRC-402) — color cycling for pie and exploded-bar charts, chart/data view toggle fix for nested controllers, world map shape updates, chart peripherals (titles, tables) updatable via chart actions, Freeform metadata prepopulation, and tooltip dark-mode fixes.
  4. Editor production tools and tab controls — a consolidated Production Tools inspector panel, granular tab visibility controls, and a unified in-browser debug surface.

No database migrations. No breaking changes to published content. All animation and tab-control attributes are additive with safe defaults; existing charts render identically until producers opt in.


What's New

1. Preact frontend runtime (PRC-17)

Background

Chart Builder's frontend (view.js + @prc/charting-library) previously ran a full React bundle in the browser — the same bundle used by the block editor. React in production weighs ~130 KB gzipped and carries scheduler and synthetic-event overhead that the static chart frontend does not need. More structurally, view.js had no way to update chart state after initial render without manipulating block attributes and triggering a PHP re-render cycle.

PRC-17 ships a purpose-built browser runtime.

What shipped

Dual build in @prc/charting-library

@prc/charting-library now produces two bundles:

BundleUsageRuntime
build/index.js (was build/editor.js)Block editorReact (unchanged)
build/frontend.jsBrowser view.jsPreact (preact/compat aliased to react/react-dom)

dependency-extraction.js at the repo root maps @prc/charting-librarywindow.prcChartingLibrary for the editor bundle. The frontend bundle is loaded as a WordPress Script Module (@prc/charting-library/frontend) and is enqueued separately by the chart controller's PHP, after the Interactivity API runtime.

The Preact frontend bundle is comparable in size to the React editor bundle (~475–490 KB uncompressed). The charting library bundles significant shared dependencies (d3, react-spring, etc.) that are the dominant cost regardless of UI runtime, so the React → Preact swap does not produce a meaningful size reduction in this package. The architectural benefit is correctness and separation of concerns: the frontend bundle is now a proper Script Module with deterministic load order, reactive Interactivity API state, and no editor-specific code paths.

useChartStore — reactive Interactivity API store

Chart state is now held in an Interactivity API store keyed by controller ID:

const { state, actions } = store('prc-chart-builder/controller', {
    state: { charts: {} },
    actions: {
        setChart(chartId, { data, config, tableData }),
        setData(chartId, data),
        setConfig(chartId, config),
        setTableData(chartId, tableData),
    },
});

applyDeepPatch handles the merge semantics: plain objects are deep-merged, arrays are replaced wholesale. config changes trigger re-render by deep-tracking the entire config subtree (fixing a bug where nested setConfig mutations didn't re-render because only the top-level reference was tracked).

useChartStore is exposed as a hook for components inside the charting library to subscribe to reactive state updates.

Chart action surface

The programmatic API used by both the debug surface and external consumers:

// Access via the debug surface (browser console or automation scripts)
window.prcChartBuilder.debug.setChart(chartId, { data, config });
window.prcChartBuilder.debug.setData(chartId, newData);
window.prcChartBuilder.debug.setConfig(chartId, newConfig);
window.prcChartBuilder.debug.getChart(chartId);
window.prcChartBuilder.debug.listCharts();

Chart peripherals — titles, subtitles, notes, source lines — can also be updated via setConfig patches, so the full chart rendering surface is reachable from the action API.


2. Animation suite (PRC-17)

Background

PRC charts are static screenshots on the first impression for most readers. Entry animations on chart reveal — bars growing from the axis, lines drawing across, pie slices sweeping in — improve reader engagement and make the data storytelling more legible, particularly on mobile where the chart occupies most of the viewport.

The animation system is fully opt-in, reduced-motion-aware, and invisible in the editor by default (instant render, no animation preview unless the author toggles "Preview animation").

What shipped

React-spring foundation

All animated components are built on react-spring with a custom TransitionProvider that coordinates:

  • Initial state: shapes at zero scale/opacity
  • Entry state: shapes animate to final geometry
  • animation.initial.follow option: secondary elements (line nodes after path, dot-plot connector after dots) sequence after their parent

Chart family coverage

Chart familyComponentAnimation
Bar (all variants)AnimatedBarHeight/width grows from axis origin
Stacked barAnimatedBarEach stack segment animates sequentially
ColumnAnimatedBarHeight grows from bottom axis
Diverging barAnimatedBarPositive bars grow right, negative bars grow left
Exploded barAnimatedBarWidth grows with stagger across groups
LineAnimatedLinePathPath draws from left to right (stroke-dashoffset technique)
AreaAnimatedAreaArea fills up from the baseline
Line nodesusePointGlideCircles glide along the path as it draws
Dot plotAnimatedCircleDots fade and scale in; connector line follows
Pie / DonutAnimatedArcSlices sweep in clockwise
Exploded pieAnimatedArcSlices sweep with offset stagger
LabelsAnimatedLabelFade at old position → tween geometry → fade in on data change

Author-facing controls

The "Animation" inspector panel in the chart block (visible on animated chart types only) exposes:

ControlConfig keyDefault
Enable animationanimation.enabledfalse
Duration (ms)animation.duration600
Easinganimation.easing'easeInOut'
Stagger delay (ms)animation.stagger80
Preview in editoranimation.previewfalse
Follow-on elementsanimation.initial.followtrue

Reduced-motion

When the reader's OS preference is prefers-reduced-motion: reduce, all animations resolve instantly. No author configuration required.

Editor behavior

The editor always renders charts in their final state unless "Preview animation" is toggled. This avoids distracting motion during block editing.


3. Bug fixes and chart action improvements (PRC-402)

Color cycling for pie and exploded-bar charts

Pie and exploded-bar charts with more categories than available palette colors now cycle through the color scale gracefully instead of repeating the last color or rendering transparent slices. Exploded-bar draggable labels also resolve color through colorScale for label/bar consistency.

Chart/data view toggle for nested controllers

The block-toolbar Chart/Data view toggle was not propagating correctly when the chart controller was nested inside another block (e.g. a grid or a columns block). The Redux store keyed by controller ID now scopes view state correctly for nested instances.

World map shape and region cuts

The world map topology has been updated with corrected boundary data and refined region cuts for Southeast Asia and Central Africa. Charts using map-world will automatically render with the corrected shapes on their next build.

Chart peripherals updatable via chart actions

setConfig patches can now reach title, subtitle, note, source, and tag fields. Previously these were excluded from the deep-patch merge path, requiring a PHP re-render to update. External tools and the debug surface can now update the full chart layout without a page reload.

Freeform metadata prepopulation

When a Freeform chart is inserted, the metadata fields (title, subtitle, note, source) are now prepopulated from the controller block's attributes. Previously Freeform charts had empty metadata until the producer manually filled them in.

Tooltip isBold dark-mode fix

Bold text in chart tooltips was not resolving the correct fill color in dark mode. The isBold style path now flows through the same getLabelFill helper used everywhere else in the renderer.

Chart peripherals stay in sync across client-side navigation

The visible data table and metadata text (title, subtitle, note, source, tag) now refresh after an Interactivity Router navigation, not only on first paint. The chart graphic already updated because it is its own data-wp-router-region; the surrounding table and metadata read the reactive store, which the router intentionally does not overwrite on navigate (populateServerData merges with override = false). chart/view.js now re-seeds the live chart slice from the fresh server payload on each navigation (syncOnNavigation), so the chart, table, and metadata reconverge together. See docs/reactive-store.md.

Data-tab table height tracks the chart as it renders

The "Data" tab table is sized to match its paired chart. Previously the match was measured once on a fixed 100ms timer, which raced the asynchronous mount of interactive charts (maps especially) and left the table too short. The height is now kept in sync with a ResizeObserver on the chart container, so the table matches as the chart finishes drawing and on any later resize. Static-image charts are unaffected.


4. Editor production tools and tab controls

Production Tools inspector panel

The chart block's inspector now has a consolidated "Production Tools" section that merges the former "Image and Data Exports" panel with new diagnostic utilities:

Reset Viewport Overrides Clears all mobile- and tablet-specific attribute overrides back to the base chart config in one click. Presented with a warning that the action is destructive (though recoverable from block history). Disabled when no overrides are present.

Force Regenerate PNG Calls a new REST endpoint (POST /wp-json/prc-chart-builder/v1/chart/{id}/regenerate-png) that clears the cached attributes hash and re-enqueues the ScreenshotOne PNG generation job. Use this when the automatic screenshot on save renders incorrectly.

Copy Data & Config Serialises the chart's current data (io.chartData) and full attribute config to JSON and copies it to the clipboard, ready to paste into a bug report or Slack message.

SVG download and PNG URL The SVG download button and live PNG URL display (previously in "Image and Data Exports") are now in this same panel.

Granular tab controls

The controller block's inspector "Tab Controls" panel replaces the single "Show tabs" toggle with individual controls for each frontend tab:

ControlDefaultNotes
Chart tabOn
Data tabOn
Allow data downloadOnDisabled automatically when Data tab is off
Download Image tabOnOnly visible when a featured image / PNG is present
Share tabOn
Include in structured data (schema.org)OnControls Dataset JSON-LD emission

Hiding a tab removes it from the rendered HTML entirely. Producers who hid all but the chart tab previously had to use custom CSS — now it is a first-class editor option.

The "Allow data download" toggle has moved from the chart block's inspector to live alongside the Data tab toggle. It is automatically disabled when the Data tab is hidden, since users cannot download data they cannot see.

Unified debug surface

window.prcChartBuilder.debug is now registered by @prc/chart-builder (src/debug/index.js) rather than @prc/charting-library. The API is identical — getChart, setChart, setData, setConfig, setTableData, listCharts, chartUpdate — but it is now colocated with the rest of the chart builder's frontend code and no longer duplicated across two packages.


Behind the scenes

  • sync-charting-version.js — new script to keep README version lines in sync across @prc/charting-library and @prc/chart-builder.
  • .gitignore — adds .worktree/ for agents using git worktrees during development.
  • BUNDLE-OPTIMIZATION.md — moved from prc-charting-library/ root into prc-charting-library/docs/ to keep docs organized.
  • Console helpers docs (prc-chart-builder/docs/console-helpers.md) — updated to document the full window.prcChartBuilder.debug API including the new action methods.
  • Removed dead updateData POC — the unused actions.updateData query-param navigation proof-of-concept in chart/view.js was removed; runtime data updates go through the setData / setChart action surface.

Files Changed (high level)

AreaChange
prc-charting-library/src/Dual build: Preact frontend bundle + existing React editor bundle
prc-charting-library/src/view.jsuseChartStore, applyDeepPatch, Interactivity API store registration
prc-charting-library/src/lib/Components/Animated*.tsxNew — animated bar, line, area, arc, circle, label components
prc-charting-library/src/lib/Components/TransitionProvider.tsxNew — animation choreography provider
prc-chart-builder/src/debug/index.jsNew — unified debug surface
prc-chart-builder/src/debug/chartUpdate.jsNew — chartUpdate helper for debug surface
prc-chart-builder/src/chart/view.jsRegister debug surface; subscribe to Interactivity store; re-seed live slice on router navigation (syncOnNavigation); remove dead updateData POC
prc-chart-builder/src/chart/class-chart.phpAdd data-wp-watch--sync-navigation directive for the navigation re-seed
prc-chart-builder/src/controller/view.jsData-tab table height tracks the chart via ResizeObserver instead of a one-shot timer
prc-chart-builder/src/chart/edit/production-controls.jsxNew — Production Tools inspector panel
prc-chart-builder/src/chart/edit/chart-controls.jsxRemove "Image and Data Exports" panel (merged into production-controls)
prc-chart-builder/src/controller/block.jsonNew tab attributes: chartTabActive, dataTabActive, downloadImageTabActive
prc-chart-builder/src/controller/Edit.jsxTab Controls panel with individual tab toggles; allowDataDownload moved here
prc-chart-builder/src/controller/class-controller.phpConditional HTML rendering gated on each tab's active attribute
prc-chart-builder/includes/class-png-export.phpNew REST endpoint for force-regenerate PNG

Upgrade Notes

  • No database migrations. All new attributes are additive with safe defaults.
  • No breaking changes to published content. Existing charts continue to render identically.
  • Animation is opt-in. No chart animates until a producer enables it in the Animation inspector panel.
  • Tab controls are additive. chartTabActive, dataTabActive, and downloadImageTabActive all default to true. Existing controller blocks render all tabs as before.
  • allowDataDownload moved. If you have automation or tooling that reads this attribute from the chart block's inspector controls, note that the UI toggle now lives in the controller block's "Tab Controls" panel. The underlying attribute location (io.allowDataDownload on the chart block) is unchanged.
  • Debug surface ownership moved. window.prcChartBuilder.debug is now populated by @prc/chart-builder. If you were relying on @prc/charting-library registering this surface (e.g. in a standalone charting-library context), you will need to include @prc/chart-builder's view.js as well.
  • Preact frontend requires a rebuild. Run npx turbo build --filter=@prc/charting-library --filter=@prc/chart-builder before deploying to ensure both the Preact frontend bundle and updated editor bundle are materialized.

Tracked Issues

  • PRC-17 — Preact frontend runtime & Animations suite
  • PRC-402 — Misc Chart Builder Bug Fixes

Changesets

  • .changeset/chart-builder-3100-production-tools-tab-controls.md
  • .changeset/charting-library-3100-debug-surface-cleanup.md
  • .changeset/chart-builder-navigation-table-sync.md

Was this helpful?