## Name HTML::D3 - A simple Perl module for generating charts using D3.js. ## Version Version 0.27 ## Synopsis ```perl use HTML::D3; my $chart = HTML::D3->new( width => 1024, height => 768, title => 'Sample Bar Chart' ); my $data = [ ['Category 1', 10], ['Category 2', 20], ['Category 3', 30] ]; my $html = $chart->render_bar_chart($data); print $html; $chart = HTML::D3->new(title => 'Sales Data'); $data = [ ['Product A', 100], ['Product B', 150], ['Product C', 200] ]; $html = $chart->render_line_chart($data); print $html; ``` ## Description HTML::D3 is a Perl module that provides functionality to create simple charts using D3.js. The module generates HTML and JavaScript code to render the chart in a web browser. Text in a chart's data and options is written into a ` ``` #### Arguments - `$data` - An array reference of data points. Each point is an array reference with two required elements - the label (string) and the value (numeric) - and an optional third element: a hash reference of extra key/value pairs to display in the tooltip after the label and value rows. ``` [$x, $y] # basic point [$x, $y, \%row] # point with extra tooltip data ``` - `\%opts` - Optional hash reference of rendering options: - `id` (string, default `'chart'`) - Override the `id` attribute of the ` element. Use this when embedding multiple charts on the same page. - `responsive` (boolean, default `0`) - If true, emit `viewBox="0 0 W H" width="100%" height="auto"` instead of fixed pixel dimensions, so the chart scales with its container. Falls back to `$self->{responsive}` when not set per call. #### Return Value A hash reference with: - `svg_id` - The `id` attribute used on the ` element. - `html` - The embeddable fragment string (Perl character string). #### Errors - Dies with `'Data must be an array of arrays'` when `$data` is not an ARRAY reference. #### Side Effects None. The method is read-only. #### Api Specification ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { id => { type => 'string', optional => 1 }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ### Render\_Zoomable\_Line\_Chart\_Snippet ```perl my $fragment = $chart->render_zoomable_line_chart_snippet($data); my $fragment = $chart->render_zoomable_line_chart_snippet($data, { animated => 1 }); # $fragment->{svg_id} - the id attribute of the element # $fragment->{html} - embeddable HTML fragment (style + button + svg + script) ``` Like `render_line_chart_snippet`, but adds brush-to-zoom: the user can drag across a range of the x-axis to zoom into that region. A _Reset zoom_ button (hidden until a zoom is active) returns the chart to its original extent. Subsequent brushes on the zoomed view zoom in further; Reset always returns to the full dataset. The caller is responsible for loading D3 in the page `. Accepts the same arguments as `render_line_chart_snippet`: an array reference of data points, each `[$x, $y]` or `[$x, $y, \%extra]`, plus an optional second argument `$opts` (hashref). #### Options - `animated` (boolean, default `0`) - when true, the initial page load animates the line drawing left-to-right via the `stroke-dashoffset` technique (1200 ms, `d3.easeLinear`), then fades in data-point circles after the line finishes (300 ms after a 1200 ms delay). Respects `prefers-reduced-motion`: when the user has requested reduced motion the line is drawn immediately at full opacity. Subsequent zoom and reset redraws are never animated regardless of this flag. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, default => {} }, } Each element of C<$data> is C<[ Str, Num ]> or C<[ Str, Num, HashRef ]>; passing C or a non-arrayref dies. Recognised C key: C (boolean, default C<0>). ``` ##### Output ``` HashRef -- C<{ svg_id =E 'chart', html =E Str }>; embeddable fragment; no DOCTYPE, no page shell, no D3 CDN tag. ``` #### Errors Dies with _Data must be an array of arrays_ if `$data` is not an arrayref. ### Render\_Multi\_Series\_Line\_Chart\_With\_Tooltips ``` $html = $chart->render_multi_series_line_chart_with_tooltips($data); ``` Generates HTML and JavaScript code to render a chart of many lines with mouseover tooltips. Accepts the following arguments: - `$data` - An array reference of series hashes. Each element is a hashref with a `name` key (string) and a `data` key (array reference of `{label, value}` hashrefs). ```perl [ { name => 'Series A', data => [{ label => 'Jan', value => 100 }, ...] }, ... ] ``` Returns a string containing the HTML and JavaScript code for the chart. Tooltip strings use `<\/b>` rather than `` for html-tidy compliance. #### Errors - Throws `Data must be an array of hashes` when `$data` is not an ARRAY reference. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, } Each element of C<$data> is a hashref with keys C (string) and C (arrayref of hashrefs with C`, or `` wrapper; D3.js must be loaded by the host page. #### Arguments - `\@series` - An array reference of series. Each series is a hash reference with a `name` (string) and a `data` array reference of `{ label => Str, value => Num }` points: ```perl [ { name => 'North', data => [ { label => 'Jan', value => 12 }, ... ] }, { name => 'South', data => [ { label => 'Jan', value => 8 }, ... ] }, ] ``` Series need not share labels: the X domain is the union of every series' labels, in first-seen order. One line and one set of dots is drawn per series, and a clickable legend toggles each series on and off. - `\%opts` - Optional hash reference: - `scheme` (string, default `'tableau10'`) - D3 categorical colour scheme (for example `'category10'`, `'set2'`, `'set3'`, `'paired'`). `categorical_schemes()` lists the names, and `palette()` hands a Perl caller the colours of one. - `x_label` (string, default `''`) - Label shown below the X axis. - `y_label` (string, default `''`) - Label shown beside the Y axis. - `animated` (boolean, default 0) - If true each line draws itself left to right by animating its stroke dash offset. Respects `prefers-reduced-motion`. - `responsive` (boolean, optional) - SVG responsive sizing override. - `id` (string, default `'chart'`) - `id` of the ` element. Returns `{ svg_id => 'chart', html => Str }`. #### Errors - Throws `Data must be an array of series` when `\@series` is not an ARRAY reference. - Throws `Each series must be a hashref with name and data` when a series is not a hashref, has no `name`, or has a `data` that is not an ARRAY reference. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { scheme => { type => 'string', optional => 1, default => 'tableau10' }, x_label => { type => 'string', optional => 1, default => '' }, y_label => { type => 'string', optional => 1, default => '' }, animated => { type => 'boolean', optional => 1, default => 0 }, responsive => { type => 'boolean', optional => 1 }, id => { type => 'string', optional => 1, default => 'chart' }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => 'chart', html => Str } ``` ### Render\_Scatter\_Chart\_Snippet ```perl my $fragment = $chart->render_scatter_chart_snippet($data); my $fragment = $chart->render_scatter_chart_snippet($data, \%opts); # $fragment->{svg_id} - the id attribute of the element # $fragment->{html} - embeddable HTML fragment (style + svg + script) ``` Generates an embeddable HTML fragment for a scatter plot with mouseover tooltips. Returns a fragment with no `, `, `, or ` wrapper; the caller is responsible for loading D3 in the page. #### Arguments - `$data` - An array reference of data points. Each point is an array reference with two required numeric elements (x, y), an optional third hash reference of extra key/value pairs shown as extra tooltip rows, and an optional fourth hash reference carrying the `series` (colour group) and `size` (bubble radius) dimensions: ```perl [$x, $y] # basic point [$x, $y, \%row] # point with extra tooltip data [$x, $y, \%row, { series => 'North', size => 42 }] # colour and size ``` - `\%opts` - Optional hash reference: - `id` (string, default `'scatter_chart'`) - `id` of the ` element. - `color` (CSS colour or `'categorical'`, default `'steelblue'`) - Fill colour for the data points. `'categorical'` uses the Tableau-10 palette. A value holding anything a CSS colour cannot, such as a quote or `<`, is ignored and the default used. - `x_label` (string, default `''`) - Label for the X axis. - `y_label` (string, default `''`) - Label for the Y axis. - `value_label` (string, default `'Value'`) - Prefix for the tooltip value row. - `colour_by_series` (boolean, default 0) - Colour each point by its `series` value instead of by point index, and draw a legend listing the series to the right of the plot. Ignored for points with no `series` value. - `scheme` (string, default `'tableau10'`) - D3 categorical colour scheme used when `colour_by_series` is set, for example `'category10'`, `'set2'`, `'set3'`, or `'paired'`. `categorical_schemes()` lists the names, and `palette()` hands a Perl caller the colours of one. - `series_col` (string, default `'Series'`) - Row label for the series value in the tooltip. - `size_col` (string, default `'Size'`) - Row label for the size value in the tooltip. - `radius_range` (arrayref of two numbers, default `[3, 15]`) - Pixel radii mapped from the smallest and largest observed `size` value. The mapping is by area (`d3.scaleSqrt`), so a point twice as large is drawn with four times the area. A point with no `size` value is drawn at the lower radius. - `animated` (boolean, default 0) - If true, circles fade in from opacity 0 on page load (400 ms). Respects `prefers-reduced-motion`. - `responsive` (boolean, default 0) - See `render_bar_chart_snippet`. #### Return Value A hash reference with `svg_id` (string) and `html` (Perl character string). #### Errors - Dies with `'Data must be an array of arrays'` when `$data` is not an ARRAY ref. - Dies with `'Each data point must be an array reference'` when an element is not an ARRAY ref. - Dies with `'Each data point must have at least 2 elements'` when a point has fewer than 2 items. - Dies with `'X value must be numeric'` when the x element is not a number. - Dies with `'Y value must be numeric'` when the y element is not a number. #### Api Specification ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { id => { type => 'string', optional => 1 }, color => { type => 'string', optional => 1, default => 'steelblue' }, x_label => { type => 'string', optional => 1, default => '' }, y_label => { type => 'string', optional => 1, default => '' }, value_label => { type => 'string', optional => 1, default => 'Value' }, colour_by_series => { type => 'boolean', optional => 1, default => 0 }, scheme => { type => 'string', optional => 1, default => 'tableau10' }, series_col => { type => 'string', optional => 1, default => '' }, size_col => { type => 'string', optional => 1, default => '' }, radius_range => { type => 'arrayref', optional => 1, default => [3, 15] }, animated => { type => 'boolean', optional => 1, default => 0 }, responsive => { type => 'boolean', optional => 1, default => 0 }, }, }, } ``` ### Render\_Table\_Snippet ```perl my $fragment = $chart->render_table_snippet($data); my $fragment = $chart->render_table_snippet($data, \%opts); # $fragment->{table_id} - the id attribute of the element # $fragment->{html} - embeddable HTML fragment (style + table + script) ``` Generates an embeddable HTML fragment for a sortable, filterable data table. Returns a fragment with no page-shell wrapper; the caller loads D3 if needed. #### Arguments - `$data` - An array reference of row array references. The first row is treated as the header row. Every subsequent row must have the same number of columns as the header. ``` [ ['Name', 'Value', 'Category'], # header ['Alpha', 300, 'A'], ['Beta', 150, 'B'], ] ``` - `\%opts` - Optional hash reference: - `id` (string, default `'data_table'`) - `id` of the ` element. - `sortable` (boolean, default 1) - If true, clicking a column header sorts the table by that column (toggle ascending/descending). - `caption` (string, default `''`) - Optional ` element text. #### Return Value A hash reference with `table_id` (string) and `html` (Perl character string). Note: returns `table_id`, not `svg_id`, because this method renders an HTML table rather than an SVG chart. #### Errors - Dies with `'Data must be an array of arrays'` when `$data` is not an ARRAY ref. - Dies with `'Data must have at least one row (header row)'` when `$data` is empty. - Dies with `'Each row must be an array reference'` when a row is not an ARRAY ref. #### Api Specification ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { id => { type => 'string', optional => 1, default => 'data_table' }, sortable => { type => 'boolean', optional => 1, default => 1 }, caption => { type => 'string', optional => 1, default => '' }, }, }, } ``` ### Render\_Stacked\_Bar\_Snippet ```perl my $result = $chart->render_stacked_bar_snippet(\@rows, \%opts); ``` Generates an embeddable stacked bar chart (no page shell, no CDN tag). Each element of `\@rows` is a hashref with three keys named by `opts`: `cat_col` (the X-axis grouping), `seg_col` (the stacking segment), and `val_col` (the numeric measure). Multiple rows sharing the same cat+seg combination are summed. Accepted `\%opts` keys: - `cat_col` (string, default `'cat'`) - row key for the X-axis category. - `seg_col` (string, default `'seg'`) - row key for the stacking segment. - `val_col` (string, default `'val'`) - row key for the numeric value. - `orient` (string `'v'` or `'h'`, default `'v'`) - bar orientation. - `scheme` (string, default `'tableau10'`) - D3 categorical colour scheme. Supported: `tableau10`, `category10`, `set2`, `set3`, `paired` - the names `categorical_schemes()` returns, whose colours `palette()` makes available to Perl. - `x_label` (string, optional) - axis label shown below the category axis. - `sort` (string, optional) - sort categories: `'value'` (desc total) or `'label'` (alpha). - `id` (string, optional) - override the default `svg_id` value. - `responsive` (boolean, optional) - SVG responsive sizing override. Returns `{ svg_id => 'stacked_bar', html => Str }`. #### Errors - Throws `Data must be an array of hashes` when `$data` is not an ARRAY reference. - Throws `Each data point must be a hash reference` when a row is not a hashref. - Throws `Value must be numeric` when a value field is not a number. - Throws `orient must be 'v' or 'h'` for an invalid `orient` value. - Throws `sort must be 'value' or 'label'` for an invalid `sort` value. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { cat_col => { type => 'string', optional => 1, default => 'cat' }, seg_col => { type => 'string', optional => 1, default => 'seg' }, val_col => { type => 'string', optional => 1, default => 'val' }, orient => { type => 'string', optional => 1, default => 'v' }, scheme => { type => 'string', optional => 1, default => 'tableau10' }, x_label => { type => 'string', optional => 1, default => '' }, sort => { type => 'string', optional => 1 }, id => { type => 'string', optional => 1, default => 'stacked_bar' }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => Str, html => Str } ``` ### Render\_Combo\_Snippet ```perl my $result = $chart->render_combo_snippet(\@rows, \%opts); ``` Generates an embeddable combo chart: bars for one measure on the left Y axis, a line for another measure on the right Y axis, sharing the same X (category) axis. Each element of `\@rows` is a hashref with at least three keys named by `opts`: `x_col` (X-axis label), `bar_col` (bar measure), and `line_col` (line measure). Accepted `\%opts` keys: - `x_col` (string, default `'x'`) - row key for the X-axis label. - `bar_col` (string, default `'bar_val'`) - row key for the bar measure. - `line_col` (string, default `'line_val'`) - row key for the line measure. - `bar_label` (string, default `'Bar'`) - legend/axis label for bars. - `line_label` (string, default `'Line'`) - legend/axis label for line. - `bar_color` (string, optional CSS colour, default `'steelblue'`) - bar fill. A value holding anything a CSS colour cannot, such as a quote or `<`, is ignored and the default used. - `line_color` (string, optional CSS colour, default `'#e15759'`) - line stroke. Checked as `bar_color` is. - `id` (string, optional) - override the default `svg_id` value. - `responsive` (boolean, optional) - SVG responsive sizing override. Returns `{ svg_id => 'combo_chart', html => Str }`. #### Errors - Throws `Data must be an array of hashes` when `$data` is not an ARRAY reference. - Throws `Each data point must be a hash reference` when a row is not a hashref. - Throws `Bar value must be numeric` when a bar value field is not a number. - Throws `Line value must be numeric` when a line value field is not a number. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { x_col => { type => 'string', optional => 1, default => 'x' }, bar_col => { type => 'string', optional => 1, default => 'bar_val' }, line_col => { type => 'string', optional => 1, default => 'line_val' }, bar_label => { type => 'string', optional => 1, default => 'Bar' }, line_label => { type => 'string', optional => 1, default => 'Line' }, bar_color => { type => 'string', optional => 1, default => 'steelblue' }, line_color => { type => 'string', optional => 1, default => '#e15759' }, id => { type => 'string', optional => 1, default => 'combo_chart' }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => Str, html => Str } ``` ### Render\_Treemap\_Snippet ```perl my $result = $chart->render_treemap_snippet(\@rows_or_tree, \%opts); ``` Generates an embeddable treemap (no page shell, no CDN tag). Leaf area is proportional to the numeric measure. Accepts two data formats: - **Flat path** (arrayref of hashrefs): each row must have a `path` key (e.g. `'Root/A/X'`) and a `value` key. The module converts this to a D3 stratify hierarchy in JS. Override the path separator with `opts->{path_sep}`. - **Nested tree** (hashref): a pre-built D3-compatible hierarchy with `name`/`children`/`value` structure. Passed directly to `d3.hierarchy()`. Accepted `\%opts` keys: - `path_sep` (string, default `'/'`) - path separator (flat format only). - `scheme` (string, default `'tableau10'`) - D3 categorical colour scheme. Supported: `tableau10`, `category10`, `set2`, `set3`, `paired` - the names `categorical_schemes()` returns, whose colours `palette()` makes available to Perl. - `label` (boolean, default `1`) - show node labels inside cells. - `id` (string, optional) - override the default `svg_id` value. - `responsive` (boolean, optional) - SVG responsive sizing override. Returns `{ svg_id => 'treemap', html => Str }`. #### Errors - Throws `Data must be an array of hashes or a hash tree` when `$data` is neither an ARRAY nor a HASH reference. - Throws `Each flat row must be a hash reference` when a flat row is not a hashref. - Throws `Each flat row must have a 'path' key` when a flat row lacks `path`. - Throws `Each flat row must have a numeric 'value' key` when a value is not numeric. #### Api Specification ##### Input ```perl { data => { type => 'arrayref | hashref' }, opts => { type => 'hashref', optional => 1, keys => { path_sep => { type => 'string', optional => 1, default => '/' }, scheme => { type => 'string', optional => 1, default => 'tableau10' }, label => { type => 'boolean', optional => 1, default => 1 }, id => { type => 'string', optional => 1, default => 'treemap' }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => Str, html => Str } ``` ### Render\_Histogram\_Snippet ```perl my $result = $chart->render_histogram_snippet(\@values, \%opts); ``` Generates an embeddable frequency histogram (no page shell, no CDN tag). `\@values` is an arrayref of numeric scalars (already extracted and coerced by the caller). Accepted `\%opts` keys: - `bins` (integer or `undef`, default `20`) - number of bins. Pass `undef` for automatic bin count using Sturges' rule: `ceil(log2(n) + 1)`. Ignored when `binned` is set. - `binned` (boolean, default 0) - treat `$data` as pre-computed bins rather than as raw values. Each element is a hashref with a `count` and either a `label` or a numeric `lo`/`hi` pair from which the label `[lo,hi)` is derived: ```perl { label => '[0,10)', count => 3 } { lo => 10, hi => 20, count => 5 } ``` The caller owns the binning, so `d3.bin()` is never called: one bar is drawn per entry, in the order supplied, and the supplied counts are authoritative. The bin labels are drawn rotated. The plot gives up as much room as they need, up to half the chart's height and a quarter of its width, so that they and `x_label` do not overlap and stay inside the chart. - `scheme` (string, optional) - D3 categorical colour scheme (for example `'tableau10'` or `'category10'`) whose first colour is used as the bar fill when `color` is not given. That colour is `colour_at($scheme, 0)`, so a caller shading the same data by hand starts from the same colour the bars do. - `x_label` (string, optional) - label shown below the X axis. - `color` (string, default `'steelblue'`) - bar fill colour. A value holding anything a CSS colour cannot, such as a quote or `<`, is ignored and the default used. - `id` (string, optional) - override the default `svg_id` value. - `responsive` (boolean, optional) - SVG responsive sizing override. Returns `{ svg_id => 'histogram', html => Str }`. #### Errors - Throws `Data must be an array of numeric values` when `$data` is not an ARRAY reference. - Throws `Each value must be numeric` when any element is non-numeric. - Throws `bins must be a positive integer` when `bins` is defined but not a positive integer. - Throws `Data must contain at least one bin` when `binned` is set and `$data` holds no bins. - Throws `Each pre-binned entry must be a hash reference` when a pre-binned element is not a hashref. - Throws `Bin count must be numeric` when a pre-binned `count` is missing or not numeric. - Throws `Bin count must not be negative` when a pre-binned `count` is negative. - Throws `Each pre-binned entry must have a label or numeric lo and hi` when a pre-binned entry has neither a `label` nor a numeric `lo`/`hi` pair. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { bins => { type => 'integer', optional => 1, default => 20 }, binned => { type => 'boolean', optional => 1, default => 0 }, x_label => { type => 'string', optional => 1, default => '' }, color => { type => 'string', optional => 1, default => 'steelblue' }, scheme => { type => 'string', optional => 1 }, id => { type => 'string', optional => 1, default => 'histogram' }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => Str, html => Str } ``` ## Support This module is provided as-is without any warranty. Please report any bugs or feature requests to `bug-html-d3 at rt.cpan.org`, or through the web interface at [http://rt.cpan.org/NoAuth/ReportBug.html?Queue=HTML-D3](http://rt.cpan.org/NoAuth/ReportBug.html?Queue=HTML-D3). I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. You can find documentation for this module with the perldoc command. ``` perldoc HTML::D3 ``` You can also look for information at: ## Bugs It would help to have the render routine to return the head and body components separately. ## See Also - [Configure an Object at Runtime](https://metacpan.org/pod/Object%3A%3AConfigure) - [Test Dashboard](https://nigelhorne.github.io/HTML-D3/coverage/) ## Author Nigel Horne ## Formal Specification ### Render\_Bar\_Chart ``` render_bar_chart : HTML::D3 × (ArrayRef | undef) → Str ∪ ⊥ pre data = undef ⇒ die "Data is not optional" pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of arrays" post result ∈ Str post " N ⇒ |result_slices| = N ∧ "Other" ∈ result_labels post opts.separator = S ⇒ " S " ⊆ result.html (HTML legend: label S value (pct%)) ``` ### Render\_Heatmap\_Snippet ``` render_heatmap_snippet : HTML::D3 × (ArrayRef | undef) × (HashRef | undef) → HashRef ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of arrays" pre ∃ pt ∈ data . ref(pt) ≠ 'ARRAY' ⇒ die "Each data point must be an array reference" pre ∃ pt ∈ data . |pt| < 3 ⇒ die "Each data point must have at least 3 elements" pre ∃ pt ∈ data . defined(pt[2]) ∧ ¬numeric(pt[2]) ⇒ die "Value must be numeric" pre opts.color_scheme = S ∧ S ∉ {YlOrRd,Blues,Greens,Purples,RdPu,YlGnBu} ⇒ die "Unknown color_scheme: S" pre opts.cell_padding = N ∧ (N < 0 ∨ N > 8) ⇒ die "cell_padding must be between 0 and 8" pre ∀ pt ∈ data . pt[2] = undef ⇒ pt ∉ result -- undef rows skipped pre ∃ pt₁,pt₂ ∈ data . pt₁[0]=pt₂[0] ∧ pt₁[1]=pt₂[1] ⇒ last-write wins post result ∈ HashRef post result.svg_id = "heatmap" post result.html ∈ Str post " N ⇒ |result_bars| = N ∧ "Other" ∈ result_labels ``` ### Render\_Multi\_Series\_Line\_Chart\_Snippet ``` render_multi_series_line_chart_snippet : HTML::D3 × (ArrayRef | undef) × (HashRef | undef) → HashRef ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of series" pre ∃ s ∈ data . ref(s) ≠ 'HASH' ⇒ die "Each series must be a hashref with name and data" pre ∃ s ∈ data . ¬defined(s.name) ∨ ref(s.data) ≠ 'ARRAY' ⇒ die "Each series must be a hashref with name and data" post result ∈ HashRef post result.svg_id = opts.id // "chart" post result.html ∈ Str post " expression post opts.animated = 1 ⇒ "stroke-dashoffset" ⊆ result.html ∧ "prefers-reduced-motion" ⊆ result.html ``` ### Render\_Scatter\_Chart\_Snippet ``` render_scatter_chart_snippet : HTML::D3 × (ArrayRef | undef) × (HashRef | undef) → HashRef ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of arrays" pre ∃ pt ∈ data . ref(pt) ≠ 'ARRAY' ⇒ die "Each data point must be an array reference" pre ∃ pt ∈ data . |pt| < 2 ⇒ die "Each data point must have at least 2 elements" pre ∃ pt ∈ data . ¬numeric(pt[0]) ⇒ die "X value must be numeric" pre ∃ pt ∈ data . ¬numeric(pt[1]) ⇒ die "Y value must be numeric" post result ∈ HashRef post result.svg_id = opts.id // "scatter_chart" post result.html ∈ Str post "" ∉ result.html ∧ "<\/b>" ∈ result.html ``` ### Render\_Treemap\_Snippet ``` render_treemap_snippet : HTML::D3 × (ArrayRef | HashRef | undef) × (HashRef | undef) → HashRef ∪ ⊥ pre ref(data) ∉ {'ARRAY','HASH'} ⇒ die "Data must be an array of hashes or a hash tree" pre ref(data) = 'ARRAY' ∧ ∃ row ∈ data . ref(row) ≠ 'HASH' ⇒ die "Each flat row must be a hash reference" pre ref(data) = 'ARRAY' ∧ ∃ row ∈ data . ¬exists(row.path) ⇒ die "Each flat row must have a 'path' key" pre ref(data) = 'ARRAY' ∧ ∃ row ∈ data . ¬numeric(row.value) ⇒ die "Each flat row must have a numeric 'value' key" post result ∈ HashRef post result.svg_id = opts.id // "treemap" post result.html ∈ Str post "" ∉ result ∧ "<\/b>" ∈ result ``` ### Render\_Multi\_Series\_Line\_Chart\_With\_Tooltips ``` render_multi_series_line_chart_with_tooltips : HTML::D3 × (ArrayRef | undef) → Str ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of hashes" post result ∈ Str post "" ∉ result ∧ "<\/b>" ∈ result ``` ### Render\_Multi\_Series\_Line\_Chart\_With\_Animated\_Tooltips ``` render_multi_series_line_chart_with_animated_tooltips : HTML::D3 × (ArrayRef | undef) → Str ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of hashes" post result ∈ Str post "" ∉ result ∧ "<\/b>" ∈ result ``` ### Render\_Multi\_Series\_Line\_Chart\_With\_Legends ``` render_multi_series_line_chart_with_legends : HTML::D3 × (ArrayRef | undef) → Str ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of hashes" post result ∈ Str post "