Bubble and histogram combinations
columnLine and areaLine share the existing combination owner and now accept bubble and histogram series assignments alongside column, line, area, scatter and rangeArea. Standalone Charts and Pivot use the same model, scales, source identities and native renderer.
const dataset = createChartDataset(rows, { category: { field: 'region' }, series: ['distance', 'revenue', 'population', 'duration', 'weight'].map(field => ({ field })),});const chart = await createChart({ container, chartType: 'columnLine', dataset, seriesOverrides: { revenue: { type: 'bubble', bubble: { x: 'distance', size: 'population' }, xAxis: 'distanceAxis', }, duration: { type: 'histogram', histogram: { value: 'weight', boundaries: [0, 5, 15, 30], aggregation: 'sum' }, xAxis: 'durationAxis', yAxis: 'frequency', }, }, axes: { xAxes: { distanceAxis: { scale: 'linear', title: 'Distance', unit: 'km' }, durationAxis: { scale: 'linear', title: 'Duration', unit: 'minutes', position: 'top' }, }, y: { title: 'Revenue' }, yAxes: { frequency: { title: 'Total weight', position: 'right' } }, }, navigation: { tooltipMode: 'shared', axes: 'xy', yAxis: 'frequency', brush: true },});The revenue owner supplies raw Y; distance and population supply raw X and size. The duration owner supplies samples; weight supplies histogram values. Bound helper measures do not acquire implicit line layers or legend entries. They stay in the canonical dataset for activation, views and raw exports. Explicitly assigning a helper its own type intentionally plots it as a separate layer. Existing range helper behavior remains supported.
Per-layer configuration
Section titled “Per-layer configuration”| Field | Contract |
|---|---|
seriesOverrides[id].type | Existing five types plus bubble and histogram. Only the two combination chart types accept these new assignments. |
bubble | Required with type: 'bubble'; exactly { x, size }, nonempty known series IDs up to 2,048 characters. The owner is Y. Channels may reuse a known measure. |
histogram | Required with type: 'histogram', including {} for automatic count bins. |
histogram.value | Nonempty known value/weight series ID up to 2,048 characters; omitted means the sample owner. |
histogram.binCount | Integer 0–256; default 0 chooses automatic binning. |
histogram.boundaries | Existing finite, strictly increasing bin-edge contract, at most 257 edges; explicit edges override bin count. |
histogram.aggregation | count (default), sum or mean, using existing missing-weight and complete-summary semantics. |
xAxis, yAxis | Existing primary/secondary/named Cartesian identities, owned by the layer, not its helper measures. |
visible, color, zIndex | Existing visibility, palette override and layer order. |
Unknown channels, missing measures/configurations, malformed boundaries, negative/noninteger bin counts, negative bubble sizes and incompatible stack/range/interpolation/error-bar fields reject updates before replacing the visible chart. Hidden layers retain validation. Histograms do not accept marker shapes; bubble/histogram layers do not accept line dashes. Existing per-source line marker modes apply only to line/area layers. The bubble renderer uses the existing relationship area-proportional radius, minimum 3 and maximum 24 SVG units (12 in previews), normalized to eligible positive loaded sizes before window filtering. Null/nonfinite X/Y/size and zero size produce no bubble; negative size rejects. marker may choose an existing series marker shape for a bubble; markerSize does not replace size-channel geometry and is rejected.
Public types are ChartBubbleLayer, ChartHistogramLayer and ChartBubbleLayerSourceRequest; Pivot exports PivotChartBubbleLayer, PivotChartHistogramLayer and PivotChartBubbleLayerSourceRequest through both public entrypoints. Old models require no migration.
X ownership and alignment
Section titled “X ownership and alignment”Column/line/area/scatter/range layers keep category-owned X identity, using category paths or authored axes.x.data / named axis maps. Bubble X and histogram samples are measure-owned numeric observations. Two layers may use different raw X values from the same canonical row; they do not borrow each other’s visible category index as a coordinate.
All layers on one logical X axis share its physical domain, transform, direction, authored bounds and window. Automatic domains include the union of assigned numeric observations and complete bin boundaries, including source full-domain hints. Sample axes default to linear when no scale is authored. Linear, log, symlog and sqrt use the existing numeric contracts; log requires positive source observations and bin boundaries. Time/category scales are rejected for bubble/histogram layers. A category-owned layer sharing a sample axis needs numeric category coordinates or an explicit numeric axis data map; string categories should use a separate axis. Named axes remain independent. Generated sample coordinate maps and inferred bounds are rendering/preflight state and never replace authored chart.model.axes.
Histogram bins retain their complete original intervals and metrics under X navigation. Window/plot clipping controls paint; it does not rebin a visible slice. Axis reversal changes projection, not source ownership or bin order. Columns on a mixed sample axis use the common projection without category-edge inset; their edge geometry clips to the plot. Existing combinations without sample layers retain their previous inset and stack/range behavior.
Independent primary/secondary/named Y windows are supported by combination geometry through the shared value-navigation owner. Bubble raw Y and computed histogram metrics contribute to their assigned Y domains; source sample magnitudes do not inflate a histogram frequency axis. Existing stack partitions and range extents remain authoritative. X/Y windows and layer order survive restore and resize.
Layer order, inspection and shared tooltips
Section titled “Layer order, inspection and shared tooltips”Default order is range area, area, histogram, column, line, scatter, bubble. zIndex overrides it; canonical series order breaks ties, including layers on different named X axes. Every layer stays within the shared plot clip.
Bubble activation uses the genuine category and Y series with raw channelValues: { x, y, size } and channelSeries; radius and projection never replace those values. Bubble points are not path-sampled. Existing path sampling affects only the existing line/area/range owners and never invents raw records.
Histogram inspection reuses the existing native bin owner. A bin activates a raw record only if its complete count is exactly one and that genuine representative is loaded. Every other bin is inspection-only, including a singleton whose source representative is not loaded. A mean/count/sum, interpolated path vertex or bin index never becomes a raw row identity.
Shared tooltips align on the same logical axis and exact raw numeric X. Raw peers use their own source category/index, including when two peers match X in different rows. Histogram peers are exposed separately through ChartTooltipContext.histogramItems, while genuine raw peers use sharedItems. Bins contain the raw X coordinate; raw peers require an exact observation and are never interpolated into a source identity. The existing 20-item limit/omission count applies. Cross-axis peers do not join merely because they occupy the same pixel. Keyboard inspection retains genuine source order and aggregate inspection semantics.
Complete sources, data views and exports
Section titled “Complete sources, data views and exports”A local dataset without a histogram summary bins its loaded raw observations, using the existing histogram algorithm. If complete statistics are supplied, they remain authoritative independently of the loaded raw slice. Source-backed combinations with histogram layers require one complete matching summary for each requested histogram partition. Providers receive request.histograms, even for a single layer:
{ sampleSeriesId: 'duration', valueSeriesId: 'weight', xAxis: 'durationAxis', yAxis: 'frequency', binCount: 3, boundaries: [0, 5, 15, 30], aggregation: 'sum', scale: 'linear',}Bubble composition providers also receive request.bubbleLayers: { seriesId, x, size, xAxis, yAxis } for each explicit bubble owner. These stable query hints identify its raw Y/X/size fields and independent windows without changing global binding ownership. They participate in request identity, so changing channels refreshes the source rather than reusing a request for another field. Providers still return genuine canonical rows.
Return dataset.analyticalFrame.derived.histograms with scope: 'all', genuine representatives and the existing summary statistics. Requested sample/value IDs, bin policy and aggregation must match. A full source X domain must contain the union of its complete partition boundaries; other layers may extend it. Missing/stale/mismatched partitions reject the response rather than silently binning the loaded slice. Changing bin policy against an old complete summary rejects the transaction: supply a matching accepted dataset/summary with the authoring change. This milestone does not introduce speculative source queries before model validation. Representable normalized histogram metrics convert back to raw axis units; unrepresentable raw metrics are rejected for mixed value axes; standalone histogram overflow normalization remains available.
createChartHistogramDataView(model, { sampleSeriesId, dataScope }) and createChartHistogramDataViews(model, options) accept combination models. Their bins describe complete statistics, and samples/loadedCount describe loaded genuine observations only. Hidden histogram layers remain available to data views. Current scope follows that layer’s X window; all scope includes every loaded row and full bin partition. Raw data views never fetch or materialize missing source rows.
CSV remains a raw matrix export. All scope exports loaded canonical cells. Current scope uses each owner layer’s own X membership and helper fields inherit the union of their owners’ windows. Bubble/path source values follow their independent Y window; histogram sample membership follows X, while aggregate Y clipping does not rewrite raw sample records. Bins, representative-only unloaded rows, radius and computed metrics are never inserted as raw CSV records. Use the histogram data-view API for bin metrics. SVG/image snapshots preserve the painted mixed geometry and remove transient inspection controls through the existing export pipeline.
Pivot authoring and limitations
Section titled “Pivot authoring and limitations”The existing series layer selector offers Bubble and Histogram. Switching to a sample layer creates an independent numeric samplesN axis atomically, preserving existing category axes. Bubble X/size selectors, histogram value/aggregation/bin-count controls and the shared validated bin-boundary input edit the same public overrides. Changing a layer type clears incompatible channel and path options. Existing X/Y assignment and layer-order controls apply. The Data tab exposes the shared sample/bin view when a histogram layer is present. Optional locale captions retain older complete locale-record compatibility.
The new locale fields under chartOptions are layerBubble, layerHistogram, layerSource, bubbleX(series), bubbleSize(series) and histogramValue(series). Existing histogram bin-count/boundary/aggregation captions are reused.
Native SVG is the supported backend. Batched SVG/WebGL equivalence is not claimed. M4’s per-datum encoding does not yet apply to combination layers and is rejected by its capability matrix; use existing series appearance. Navigator overview is explicitly rejected for sample-owned compositions, preventing a raw-line miniature from misrepresenting a histogram. Numeric gestures/windows/shared hover remain available. No polar composition, arbitrary financial panes, mixed time/sample axes, component slots or new histogram area/density layer is included.