@peter.prib/renderengine 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +454 -302
  2. package/dist/renderengine-workspace.umd.js +2203 -113
  3. package/dist/renderengine.umd.js +2203 -113
  4. package/documentation/REFERENCE.md +30 -1
  5. package/package.json +8 -3
  6. package/src/chartCatalog.js +50 -3
  7. package/src/charting/Chart3D.js +4 -2
  8. package/src/charting/Hierarchy.js +28 -0
  9. package/src/charting/ask/AskBar.js +388 -0
  10. package/src/charting/ask/AskView.js +400 -0
  11. package/src/charting/charts/AreaChart.js +20 -3
  12. package/src/charting/charts/BarChart3D.js +2 -2
  13. package/src/charting/charts/BarChart3DOrbit.js +3 -1
  14. package/src/charting/charts/BoxPlotChart.js +2 -2
  15. package/src/charting/charts/BubbleChart.js +4 -1
  16. package/src/charting/charts/ChordDiagram.js +4 -4
  17. package/src/charting/charts/DensityChart.js +1 -1
  18. package/src/charting/charts/FunnelChart.js +1 -1
  19. package/src/charting/charts/HeatmapChart.js +4 -1
  20. package/src/charting/charts/HistogramChart.js +2 -2
  21. package/src/charting/charts/IcicleChart.js +47 -0
  22. package/src/charting/charts/LollipopChart.js +104 -0
  23. package/src/charting/charts/MarimekkoChart.js +75 -0
  24. package/src/charting/charts/OutlineChart.js +10 -8
  25. package/src/charting/charts/ParallelCoordinatesChart.js +2 -2
  26. package/src/charting/charts/ParetoChart.js +92 -0
  27. package/src/charting/charts/PipeChart.js +5 -2
  28. package/src/charting/charts/PopulationPyramidChart.js +4 -4
  29. package/src/charting/charts/RadarChart.js +5 -4
  30. package/src/charting/charts/RadialBarChart.js +2 -2
  31. package/src/charting/charts/SankeyDiagram.js +4 -4
  32. package/src/charting/charts/ScatterChart.js +6 -3
  33. package/src/charting/charts/StackedBarChart.js +82 -11
  34. package/src/charting/charts/StackedBarChart3DOrbit.js +5 -2
  35. package/src/charting/charts/StreamGraphChart.js +8 -0
  36. package/src/charting/charts/SunburstChart.js +2 -2
  37. package/src/charting/charts/TreemapChart.js +4 -4
  38. package/src/charting/charts/ViolinChart.js +2 -2
  39. package/src/charting/charts/WaterfallChart.js +2 -2
  40. package/src/charting/charts/WordCloudChart.js +2 -2
  41. package/src/charting/pivot/PivotChart.js +205 -13
  42. package/src/charting/pivot/PivotGridChart.js +1 -1
  43. package/src/charting/pivot/PivotView.js +544 -21
  44. package/src/index.js +98 -2
package/src/index.js CHANGED
@@ -33,6 +33,10 @@ import { LagPlotChart } from './charting/charts/LagPlotChart.js';
33
33
  import { TreemapChart } from './charting/charts/TreemapChart.js';
34
34
  import { SunburstChart } from './charting/charts/SunburstChart.js';
35
35
  import { OutlineChart } from './charting/charts/OutlineChart.js';
36
+ import { IcicleChart } from './charting/charts/IcicleChart.js';
37
+ import { ParetoChart } from './charting/charts/ParetoChart.js';
38
+ import { LollipopChart } from './charting/charts/LollipopChart.js';
39
+ import { MarimekkoChart } from './charting/charts/MarimekkoChart.js';
36
40
  import { TableChart } from './charting/charts/TableChart.js';
37
41
  import { ChartChooser } from './charting/ChartChooser.js';
38
42
  import { TableView } from './charting/table/TableView.js';
@@ -40,6 +44,8 @@ import { TableViewChart } from './charting/table/TableViewChart.js';
40
44
  import { PivotView } from './charting/pivot/PivotView.js';
41
45
  import { PivotGridChart } from './charting/pivot/PivotGridChart.js';
42
46
  import { PivotChart } from './charting/pivot/PivotChart.js';
47
+ import { AskView } from './charting/ask/AskView.js';
48
+ import { AskBar } from './charting/ask/AskBar.js';
43
49
  import { RadarChart } from './charting/charts/RadarChart.js';
44
50
  import { FunnelChart } from './charting/charts/FunnelChart.js';
45
51
  import { WaterfallChart } from './charting/charts/WaterfallChart.js';
@@ -228,7 +234,8 @@ import {
228
234
  // separate browser-only entry: import 'renderengine/src/workspace.js' directly.
229
235
 
230
236
  export {
231
- Mat4, OrbitCamera, CHART_CATALOG, getChartCatalogEntry, chartRegistry, ChartChooser, TableChart, TableView, TableViewChart, PivotView, PivotGridChart, PivotChart,
237
+ Mat4, OrbitCamera, CHART_CATALOG, getChartCatalogEntry, chartRegistry, ChartChooser, TableChart, TableView, TableViewChart, PivotView, PivotGridChart, PivotChart, AskView, AskBar,
238
+ ParetoChart, LollipopChart, MarimekkoChart, IcicleChart,
232
239
  DIAGRAM_CATALOG, getDiagramCatalogEntry, diagramRegistry,
233
240
  TREE_MODE_CATALOG, treeModeRegistry, getTreeModeCatalogEntry,
234
241
  AXIS_KIND, ENCODING_CHANNEL, COORD_SYSTEM, COLOR_MODE, CAMERA_MODE,
@@ -1500,6 +1507,39 @@ export class RenderEngine {
1500
1507
  const back = this.renderer.text('◂ Table', 8, 14, { fill: '#2b5fd9', fontSize: '12px', verticalAlign: 'middle' });
1501
1508
  back?.addEventListener?.('click', () => this._drawResultTable(view, options));
1502
1509
  if (back?.style) back.style.cursor = 'pointer';
1510
+ const choices = view.chartChoices();
1511
+ if (choices.length > 1) {
1512
+ const pick = this.renderer.text(`${choice.label} ▾`, 68, 14, { fill: '#2b5fd9', fontSize: '12px', verticalAlign: 'middle', tooltip: choice.reason });
1513
+ const show = options.showMenu ?? ((x, y, items) => PopupMenu.show(x, y, items));
1514
+ pick?.addEventListener?.('click', (e) => show(e.clientX, e.clientY, choices.map(c => ({
1515
+ label: `${c.label}${c.key === choice.key ? ' ✓' : ''}`,
1516
+ action: () => this._drawResultChart(view, c, options),
1517
+ }))));
1518
+ if (pick?.style) pick.style.cursor = 'pointer';
1519
+ }
1520
+ }
1521
+
1522
+ /**
1523
+ * Mounts an interactive `AskBar` (question input, configurable next-word prediction in a
1524
+ * scrollable list, semantic sense/reference/relation badges, and sample query pills) into
1525
+ * `container` (or links `resultEngine: this` when called as `engine.askBar(container, options)`).
1526
+ * @param {HTMLElement|string|object} containerOrOptions host container element/id, or options when mounting into `this.container`
1527
+ * @param {object} [options] `AskBar` / `AskView` options (`suggest`, `measures`, `dimensions`, `members`, `sampleQuestions`, `visibleCount`, `predictChoices`, `onAsk`, etc.)
1528
+ * @returns {AskBar}
1529
+ */
1530
+ askBar(containerOrOptions, options = {}) {
1531
+ const isPlainOptions = containerOrOptions
1532
+ && typeof containerOrOptions === 'object'
1533
+ && !containerOrOptions.nodeType
1534
+ && typeof containerOrOptions.appendChild !== 'function';
1535
+ const container = isPlainOptions ? this.container : containerOrOptions;
1536
+ const opts = isPlainOptions ? containerOrOptions : options;
1537
+ return new AskBar(container, { resultEngine: this, ...opts });
1538
+ }
1539
+
1540
+ /** Static helper: `RenderEngine.askBar(container, options)` constructs and mounts an `AskBar`. */
1541
+ static askBar(container, options = {}) {
1542
+ return new AskBar(container, options);
1503
1543
  }
1504
1544
 
1505
1545
  /**
@@ -1550,7 +1590,8 @@ export class RenderEngine {
1550
1590
  pivotChart(view, options = {}) {
1551
1591
  if (!this.renderer) return null;
1552
1592
  const chart = new PivotChart(view, options);
1553
- chart.detach = view.listen(() => this._drawPivotChart(chart, options));
1593
+ chart.redraw = () => this._drawPivotChart(chart, options);
1594
+ chart.detach = view.listen(chart.redraw);
1554
1595
  this._drawPivotChart(chart, options);
1555
1596
  return chart;
1556
1597
  }
@@ -1561,15 +1602,19 @@ export class RenderEngine {
1561
1602
  if (choice === null) {
1562
1603
  this.renderer.clear();
1563
1604
  this.renderer.text('No chart fits what the grid shows', 8, 14, { fill: '#666', fontSize: '12px', verticalAlign: 'middle' });
1605
+ options.onDraw?.(null, chart);
1564
1606
  return;
1565
1607
  }
1566
1608
  // No title unless one is given: the grid beside it says what is charted, and the link below
1567
1609
  // names the chart (with the chooser's reason as its tooltip).
1568
1610
  this.renderChartType(choice.key, choice.data, {
1611
+ ...choice.options,
1569
1612
  title: options.title,
1570
1613
  legend: true, // a series per column member: which colour is which must be said
1571
1614
  onDatumClick: (datum) => chart.click(datum),
1615
+ onNodeClick: (node) => chart.click({ label: node.label }),
1572
1616
  });
1617
+ options.onDraw?.(choice, chart);
1573
1618
  // Which chart, and the menu to change it, drawn over the chart as resultView's "◂ Table" is.
1574
1619
  if (!this.renderer.supportsSceneGraph) return;
1575
1620
  const pick = this.renderer.text(`${choice.label} ▾`, 8, 14, { fill: '#2b5fd9', fontSize: '12px', verticalAlign: 'middle', tooltip: choice.reason });
@@ -1587,6 +1632,57 @@ export class RenderEngine {
1587
1632
  this.fitToContainer();
1588
1633
  }
1589
1634
 
1635
+ /**
1636
+ * Renders an icicle chart — rectangular hierarchical partition chart (top-down bands by depth,
1637
+ * width proportional to value within each parent's span).
1638
+ * @param {Array<{label: string, value?: number, children?: Array}>} data
1639
+ * @param {object} [options]
1640
+ */
1641
+ icicleChart(data, options = {}) {
1642
+ if (!this.renderer) return;
1643
+ this._chart3D = false;
1644
+ this._chartState = { type: 'icicle', data, options };
1645
+ this._renderChart(new IcicleChart(this.renderer, data, options));
1646
+ }
1647
+
1648
+ /**
1649
+ * Renders a Pareto chart — categories sorted descending with a cumulative percentage line (0–100%)
1650
+ * on a right-hand axis and an 80% cutoff reference line.
1651
+ * @param {Array<{label: string, value: number}>} data
1652
+ * @param {object} [options]
1653
+ */
1654
+ paretoChart(data, options = {}) {
1655
+ if (!this.renderer) return;
1656
+ this._chart3D = false;
1657
+ this._chartState = { type: 'pareto', data, options };
1658
+ this._renderChart(new ParetoChart(this.renderer, data, options));
1659
+ }
1660
+
1661
+ /**
1662
+ * Renders a lollipop chart — stem-and-dot alternative to bars for 1D or multi-series comparisons.
1663
+ * @param {Array<{label: string, value: number}>|Array<{name: string, values: Array<{label: string, value: number}>}>} data
1664
+ * @param {object} [options]
1665
+ */
1666
+ lollipopChart(data, options = {}) {
1667
+ if (!this.renderer) return;
1668
+ this._chart3D = false;
1669
+ this._chartState = { type: 'lollipop', data, options };
1670
+ this._renderChart(new LollipopChart(this.renderer, data, options));
1671
+ }
1672
+
1673
+ /**
1674
+ * Renders a Marimekko (mosaic) chart — variable-width 100%-stacked columns where column width is
1675
+ * proportional to each category's total and segment height is each series' share within that category.
1676
+ * @param {Array<{name: string, values: Array<{label: string, value: number}>}>|Array<{label: string, values: number[]}>} data
1677
+ * @param {object} [options]
1678
+ */
1679
+ marimekkoChart(data, options = {}) {
1680
+ if (!this.renderer) return;
1681
+ this._chart3D = false;
1682
+ this._chartState = { type: 'marimekko', data, options };
1683
+ this._renderChart(new MarimekkoChart(this.renderer, data, options));
1684
+ }
1685
+
1590
1686
  /**
1591
1687
  * Renders a waterfall chart — running-total bars, each floating from the
1592
1688
  * previous cumulative value to the new one (a "delta" bar), except