Release: Chart Builder
3.8.0· PRC Platform1.5Work period: April 2026 Scope:prc-chart-builder,prc-charting-library
Overview
Chart Builder 3.8.0 is a broad quality-of-life release focused on data integrity, editor ergonomics, and chart expressiveness. Five major features land together:
- Table data validation & typed columns — the Power Table block gains per-column data types and live validation, and Chart Builder registers named schemas (geo maps, time series) that gate chart sync on clean data.
- Multi-user editor presence & locking — see who's editing a chart alongside you, and prevent accidental conflict writes.
- Error bars on dot plots — per-point uncertainty visualization with full styling control.
- Net value labels for diverging bar charts — show the net total on each side of a diverging bar without manual label math.
- Chart/Data view toggle — switch the editor between chart view, data view, or both-at-once on a per-user, per-block basis.
Also in the box: automatic publishing of draft chart CPTs when a referencing post publishes, JSON-LD improvements for search-engine discoverability, a treemap refresh, a substantial Pie chart refactor, and removal of the legacy editor-side PNG generation flow.
What's New
1. Table data validation & typed columns
Background
Chart Builder has always been downstream of whatever is in the chart's source table — if the table contained a stray "N/A" in a number column, or a malformed ISO-3 country code on a choropleth map, the chart would silently render garbage (or nothing at all), and the error would only be caught by a human reviewer. This was especially painful for map charts, which require tightly formatted geographic codes, and for time-series charts, which need a real date column.
3.8.0 adds a real data-validation layer at the table level and wires it into Chart Builder so that bad data is caught in the editor, before anything is pushed to the chart.
Per-column data types
The Power Table block (core/table replacement in prc-block-library) now supports a columnMeta[].dataType attribute with the following values:
| Type | Accepts | Example |
|---|---|---|
auto | Anything (default — infers type) | — |
text | Anything | "United States" |
number | Integers or decimals, with optional commas and % | 1,234.56, 42% |
date | ISO 8601, US (M/D/YYYY), EU (D.M.YYYY), or year-only | 2024-01-15, 1/15/24, 2024 |
currency | Numbers with $, €, £, ¥, or ₹ symbol | $1,234.56 |
percentage | Number followed by % | 42% |
url | http:// or https:// URL | https://example.com |
fips | 2-digit US state or 5-digit US county FIPS code | 06, 06075 |
iso3alpha | ISO 3166-1 alpha-3 country code (incl. PRC map extensions like XKX for Kosovo) | USA, DEU, XKX |
iso3numeric | ISO 3166-1 numeric country code (zero-padded or not) | 840, 276, 383 |
Column type is set from the table's block-toolbar "Column type" menu on a per-column basis. Empty cells always pass validation.
Live cell validation
Every cell is validated on edit. Invalid cells pick up a .is-cell-invalid style in the editor so producers can see exactly which cells failed before they dig into the inspector panel.
Validation inspector panel
A new "Data validation" inspector panel surfaces all current validation errors with row and column coordinates and a human-readable message — e.g. body row 4 col 2: Expected an ISO 3166-1 alpha-3 country code (e.g. USA). The panel caps visible errors at five with an overflow count so a badly malformed paste doesn't blow out the sidebar.
Toolbar error-count button
A new block-toolbar button shows the current error count and, on click, jumps the user straight to the first invalid cell. This makes validation discoverable even when the inspector isn't open.
Named validation schemas
The table block exposes a PHP filter prc_table_validation_schemas so any plugin can register a named schema — a set of requiredTypes that must be present on at least one column. Registered schemas are surfaced to the editor via window.prcTableValidationSchemas and appear in the Data validation panel's schema dropdown.
Chart Builder registers five schemas out of the box:
| Slug | Label | Required column types |
|---|---|---|
geo-state | US State Map | fips |
geo-county | US County Map | fips |
geo-country | World Map (Alpha-3) | iso3alpha |
geo-country-numeric | World Map (Numeric) | iso3numeric |
timeseries | Time Series | date, number |
Chart sync gating
This is the piece that matters most for chart quality: when a chart block detects that its source table has any column type other than auto declared or an active validation schema, it flips into "validated mode." In that mode, the chart refuses to sync data from the table into the chart attributes while isValid is false. Producers see an inline Notice warning them that their data is invalid and the chart is showing a stale render. Fixing the data immediately unblocks the sync. No more silently shipping a chart with bad geography codes or mixed numeric/text columns.
Tables that haven't opted into typed columns continue to work exactly as before — validation is opt-in per column.
For plugin authors
Other plugins can register their own schemas:
add_filter( 'prc_table_validation_schemas', function( $schemas ) {
$schemas[] = array(
'slug' => 'my-custom-schema',
'label' => 'My Custom Schema',
'requiredTypes' => array( 'number', 'percentage' ),
);
return $schemas;
} );
The table block itself registers zero schemas — it only provides the infrastructure. Chart Builder happens to be the first consumer; other chart types, map plugins, or report builders can register their own.
2. Multi-user editor presence & locking
Background
Chart Builder's editor has a few panels that are easy to stomp on when two people open the same chart at once — data entry, category ordering, label customizations. With WordPress Real-Time Collaboration rolling out across PRC sites, the chart editor needed first-class presence awareness so editors can see who else is in the chart and avoid overwriting each other's work.
What shipped
- Presence declaration — each chart editor session publishes a lightweight presence record via the new
useDeclarePresencehook (from@prc/hooks). The record includes the current user, the post ID, and which inspector panel they currently have focused. - Presence consumption —
usePresenceUserssubscribes to all active presence records for a given chart and returns the other users currently editing it. - Block-level lock — the chart controller wires both hooks together in
use-chart-editor-presence.js. When another user's presence is detected on the same chart, the block switches into a read-only visual state and writes to attributes are disabled. The authoring user sees who has the lock. - Inspector panel focus — panels in the chart block (Data, Style, Labels, Axes, etc.) broadcast their focused state so collaborators can see exactly which section another user is working in. The existing
inspector-focus-context.jswas extended to carry that metadata. - Synced chart presence —
synced-chartblocks participate in the same presence model, so a user editing a synced chart preview also shows up as active on the underlying chart post.
Hook renames
Two @prc/hooks exports were renamed to better reflect intent:
| Old name | New name |
|---|---|
usePublishPresence | useDeclarePresence |
usePresenceFelt | usePresenceUsers |
Existing callers across the platform were updated in the same PR; no plugin outside the monorepo consumes these directly.
3. Error bars on dot plots
Background
Dot plots are the natural home for point-estimate-plus-uncertainty visualizations (survey margins of error, confidence intervals, etc.), but until now there was no supported way to render error bars in Chart Builder. Researchers either exported the chart type as a scatter plot with post-hoc annotations or dropped back to Illustrator.
What shipped
- ShapePanel → Error Bars — a new
ErrorBarPanelinside the per-point ShapePanel popover lets editors set:- Lower and upper bound values (numeric, independent of the y value)
- Stroke color (with theme token support)
- Stroke width
- Opacity
- Dash array (for styled "approximate" error bars)
- State management — a new
useErrorBarCustomizationshook stores per-point error-bar config under the existingshapesattribute structure, using the same stable keying scheme as the rest of the ShapePanel customizations. No new top-level attribute was added. - Rendering — the DotPlot component now draws whiskered error bars under each point, in both light and dark contexts. Error bars respect the same color-interpolation rules as other label elements (the standardized
getLabelFillhelper). - Hit-test improvements — a voronoi hit model was added to DotPlot to keep hover/tooltip and label-drag targets accurate even when error-bar whiskers extend beyond the point itself.
4. Net value labels for diverging bar charts
Background
Diverging bar charts (two categories fanning out from a central axis — e.g., Favorable vs. Unfavorable) often need a "net" label summarizing each side — the sum of values, or the difference between the two sides, anchored to the end of each bar group. Authors used to add these manually with the DraggableLabel block; now Chart Builder renders them.
What shipped
NetValueLabelscomponent — a new component renders net totals at each end of every diverging bar row (horizontal) or column (vertical). Values are computed from the chart's rendered data, so they track edits automatically.- Inspector controls — a new
net-value-controls.jsxpanel exposes:- Enable/disable per side (left/right, or top/bottom for vertical)
- Per-side text color, font size, and offset
- Label format (sum, difference, custom prefix/suffix)
- Dark-mode aware — labels use the standardized
getLabelFillhelper so they contrast correctly against the chart background regardless of theme. - DraggableLabel updates —
DraggableLabelwas tightened in the same work so net-value labels and draggable labels share positioning logic.
5. Chart / Data view toggle
Background
The block-editor view of a chart has historically shown both the chart and the data table stacked together. That works well for quick checks, but for long data sets or narrow viewports it clutters the editor. Authors needed a way to focus on one or the other.
What shipped
- Block toolbar button — a new "Switch to data / Switch to chart" button in the block toolbar toggles between chart-only and data-only views.
- Inspector "Show both" toggle — a new
view-mode-controls.jsxinspector panel adds an explicit three-way choice: chart-only, data-only, or both. - Controller Redux store — view state is held in a new chart-controller Redux store, keyed by
controllerId, so the chart block, data table block, and controller wrapper stay in sync without attribute round-trips. This prevents view-mode toggling from dirtying the post. - Editor-only preference — view mode is a per-user authoring preference. It does not persist to the database and does not affect the published front-end output.
- Removal of
hide-table-handler.jsx— the previous ad-hoc table hiding logic was removed in favor of the new store-based flow.
6. Synced chart auto-publish
Background
The synced-chart block lets posts reference a chart CPT. Before this release, if a producer embedded a draft chart in a post and published the post, the chart itself stayed in draft — and the front-end silently rendered nothing. A separate manual "publish the chart first" step was required.
What shipped
A new Synced_Chart_Auto_Publish class hooks into the platform-wide prc_platform_on_publish and prc_platform_on_update actions. When a post publishes (or updates), the handler:
- Scans the post's rendered blocks for
synced-chartreferences. - For each referenced chart CPT that is still in
draft,pending, orfuture, transitions it topublish. - Logs the transition for audit.
This makes the chart lifecycle follow the parent post's lifecycle by default, matching how editors already think about it.
7. JSON-LD improvements
Dataset.description prefers alt_text
Chart CPTs emit schema.org/Dataset JSON-LD for search-engine discoverability. The description field now prefers the chart's alt_text (authored for accessibility) and falls back to the subtitle-derived description only when alt_text is empty. This gives search engines the best short summary available.
New isPartOf field
Dataset JSON-LD now includes an isPartOf array listing every published post that references the chart CPT. This surfaces the chart → story relationship to crawlers and structured-data consumers.
Synced chart reference panel filters revisions
The synced-chart inspector panel previously listed post revisions alongside the canonical post when showing "where this chart is used." Revisions are now filtered out, so the list matches what front-end users actually see.
8. Treemap sort and label refinements
The treemap variation template was updated — sort order, label rendering, and category handling were all refined. data-controls.jsx was reorganized so treemap-specific controls live together. No attribute migration was required; existing treemaps pick up the new behavior automatically.
9. Behind the scenes
- Label fill resolution consolidated — every chart component now uses a single
getLabelFillhelper. The olderresolveLabelFillhelper was folded into it. This gives consistent dark-mode label contrast across all chart types. - Pie chart refactor —
Pie.tsxwas rewritten, dropping from ~1280 to ~530 lines by consolidating rendering paths and deduplicating slice/label logic. No user-visible behavior change. - Chart block migration tweaks — small adjustments to the v1 → v2 migration path around label controls and contrast values.
- Editor-side PNG generation removed —
chart-png-panel.jsand the editor-sidecreatePNGflow were deleted (#2818). The server-side PNG pipeline introduced in 3.6.0 is now the sole path for chart images.image-exports.jswas trimmed to match. - Version constant aligned —
PRC_CHART_BUILDER_VERSIONbumped from the stale3.1.0to3.8.0to match the plugin header.
Files Changed (high level)
| Area | Change |
|---|---|
prc-block-library/src/table/utils/validation.ts | New — validation engine with per-type validators, FIPS / ISO-3 alpha / ISO-3 numeric datasets |
prc-block-library/src/table/utils/column-meta.ts | New — resolves effective ColumnMeta and bridges legacy parallel arrays |
prc-block-library/src/table/settings/table-validation-settings.tsx | New — inspector panel |
prc-block-library/src/table/settings/table-validation-toolbar.tsx | New — block-toolbar error-count button |
prc-block-library/src/table/class-table.php | Collects prc_table_validation_schemas filter output and localizes it to window.prcTableValidationSchemas |
prc-block-library/src/table/block.json | New columnMeta, validationSchema, isValid attributes |
prc-chart-builder/src/controller/class-controller.php | Registers five built-in schemas via prc_table_validation_schemas filter |
prc-chart-builder/src/chart/edit/index.jsx | Reads tableIsValid / tableValidationSchema from table context; gates chart sync; renders inline warning |
@prc/hooks | Renamed usePublishPresence → useDeclarePresence, usePresenceFelt → usePresenceUsers |
src/controller/use-chart-editor-presence.js | New — controller-level presence + lock wiring |
src/chart/edit/inspector-focus-context.js | Extended to broadcast panel focus |
src/synced-chart/use-chart-presence.js | New — synced-chart participation in presence model |
src/chart/edit/popover/ErrorBarPanel.jsx | New — per-point error-bar controls |
src/chart/edit/popover/hooks/useErrorBarCustomizations.js | New — error-bar state hook |
prc-charting-library/src/.../DotPlot.tsx | Error-bar rendering + voronoi hit model |
prc-charting-library/src/.../NetValueLabels.tsx | New — net value label component |
src/chart/edit/inspector/net-value-controls.jsx | New — net label inspector panel |
src/chart/edit/inspector/view-mode-controls.jsx | New — view mode inspector toggle |
src/controller/Edit.jsx / src/controller/block.json | Controller view-mode store + toolbar button |
src/chart/edit/hide-table-handler.jsx | Removed |
includes/class-synced-chart-auto-publish.php | New — auto-publish class |
includes/class-json-ld.php (or equivalent) | alt_text preference, isPartOf field, revision filter |
src/variations/treemap.js + data-controls.jsx | Treemap sort/label updates |
prc-charting-library/src/.../getLabelFill.ts | Consolidation of resolveLabelFill |
prc-charting-library/src/.../Pie.tsx | Full refactor |
src/chart/edit/chart-png-panel.js | Removed |
src/chart/edit/image-exports.js | Trimmed |
prc-chart-builder.php | PRC_CHART_BUILDER_VERSION → 3.8.0 |
Upgrade Notes
- No database migrations. All new attributes are additive with sensible defaults.
- No breaking changes for published content. Existing charts continue to render identically.
- Table validation is opt-in. Tables with every column set to
autobehave exactly as before. The chart-sync gate only activates when a table declares a non-autocolumn type or picks an active validation schema. - Plugin authors: the
prc_table_validation_schemasfilter is public API. Any plugin that embeds the Power Table and has schema requirements should register them via this filter rather than reimplementing validation. - Presence hooks renamed. The two renames (
usePublishPresence→useDeclarePresence,usePresenceFelt→usePresenceUsers) only affect intra-monorepo callers, which were updated in the same PR. External plugins should not be consuming these. - Editor-side PNG generation is gone. If any custom integration relied on
createPNGfrom the chart editor, migrate to the server-side PNG endpoint introduced in 3.6.0. - Synced chart auto-publish is on by default. Draft charts referenced by a publishing post will transition to
publishautomatically. Posts that reference charts they don't intend to publish should hold the referencing post as draft.
Tracked Issues
#2565— Table data validation, typed columns, schemas, chart sync gate#2850— Editor presence & locking#2121— Dot plot error bars#2745— Net value labels for diverging bars#2808— Chart / Data view toggle#2814— JSON-LD improvements#2818— Unhook editor-side PNG generation#2873— Treemap refinements#2807— 3.8.0 tracking / label fill consolidation / Pie refactor