@rowsncolumns/charts 28.1.8 → 28.1.11

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 (47) hide show
  1. package/dist/cjs/basic-chart/basic-chart.d.ts.map +1 -1
  2. package/dist/cjs/basic-chart/basic-chart.js +538 -430
  3. package/dist/cjs/basic-chart/helpers.d.ts.map +1 -1
  4. package/dist/cjs/basic-chart/helpers.js +2 -0
  5. package/dist/cjs/plotly/basic-chart/basic-chart.d.ts.map +1 -1
  6. package/dist/cjs/plotly/basic-chart/basic-chart.js +333 -184
  7. package/dist/cjs/plotly/basic-chart/helpers.d.ts.map +1 -1
  8. package/dist/cjs/plotly/basic-chart/helpers.js +2 -0
  9. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  10. package/dist/cjs/utils/bubble.d.ts +34 -1
  11. package/dist/cjs/utils/bubble.d.ts.map +1 -1
  12. package/dist/cjs/utils/bubble.js +39 -13
  13. package/dist/cjs/utils/echarts-overlays.d.ts +46 -0
  14. package/dist/cjs/utils/echarts-overlays.d.ts.map +1 -0
  15. package/dist/cjs/utils/echarts-overlays.js +134 -0
  16. package/dist/cjs/utils/hierarchy.d.ts +23 -1
  17. package/dist/cjs/utils/hierarchy.d.ts.map +1 -1
  18. package/dist/cjs/utils/hierarchy.js +179 -55
  19. package/dist/cjs/utils/overrides.d.ts.map +1 -1
  20. package/dist/cjs/utils/overrides.js +15 -3
  21. package/dist/cjs/utils/trendline.d.ts +7 -1
  22. package/dist/cjs/utils/trendline.d.ts.map +1 -1
  23. package/dist/cjs/utils/trendline.js +82 -18
  24. package/dist/esm/basic-chart/basic-chart.d.ts.map +1 -1
  25. package/dist/esm/basic-chart/basic-chart.js +381 -251
  26. package/dist/esm/basic-chart/helpers.d.ts.map +1 -1
  27. package/dist/esm/basic-chart/helpers.js +2 -0
  28. package/dist/esm/plotly/basic-chart/basic-chart.d.ts.map +1 -1
  29. package/dist/esm/plotly/basic-chart/basic-chart.js +253 -58
  30. package/dist/esm/plotly/basic-chart/helpers.d.ts.map +1 -1
  31. package/dist/esm/plotly/basic-chart/helpers.js +2 -0
  32. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  33. package/dist/esm/utils/bubble.d.ts +34 -1
  34. package/dist/esm/utils/bubble.d.ts.map +1 -1
  35. package/dist/esm/utils/bubble.js +35 -11
  36. package/dist/esm/utils/echarts-overlays.d.ts +46 -0
  37. package/dist/esm/utils/echarts-overlays.d.ts.map +1 -0
  38. package/dist/esm/utils/echarts-overlays.js +135 -0
  39. package/dist/esm/utils/hierarchy.d.ts +23 -1
  40. package/dist/esm/utils/hierarchy.d.ts.map +1 -1
  41. package/dist/esm/utils/hierarchy.js +168 -50
  42. package/dist/esm/utils/overrides.d.ts.map +1 -1
  43. package/dist/esm/utils/overrides.js +15 -3
  44. package/dist/esm/utils/trendline.d.ts +7 -1
  45. package/dist/esm/utils/trendline.d.ts.map +1 -1
  46. package/dist/esm/utils/trendline.js +67 -14
  47. package/package.json +3 -3
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toPlotlyHierarchy = exports.buildHierarchyTree = exports.extractHierarchyRows = exports.getHierarchyHeaderTitle = void 0;
3
+ exports.hierarchyNodeColors = exports.toPlotlyHierarchy = exports.buildHierarchyTree = exports.extractHierarchyRows = exports.getHierarchyHeaderTitle = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var flattenChartData = function (chartData, extractor, hiddenStrategy, skipFirstRow) {
6
6
  if (skipFirstRow === void 0) { skipFirstRow = false; }
@@ -22,10 +22,6 @@ var toLabelString = function (value) {
22
22
  return "";
23
23
  return "".concat(value).trim();
24
24
  };
25
- var toParentLabel = function (value) {
26
- var label = toLabelString(value);
27
- return label === "" ? null : label;
28
- };
29
25
  var toNumericValue = function (value) {
30
26
  if (typeof value === "number" && Number.isFinite(value)) {
31
27
  return value;
@@ -79,75 +75,186 @@ var getHierarchyHeaderTitle = function (spec, options) {
79
75
  return undefined;
80
76
  };
81
77
  exports.getHierarchyHeaderTitle = getHierarchyHeaderTitle;
78
+ /**
79
+ * Lay the rows out as Excel does: one column per level (`parentLabels`
80
+ * entries, top level first) and the label column as the innermost level.
81
+ * Returns, per row, the filled level cells up to the row's leaf.
82
+ *
83
+ * A blank level cell BEFORE the row's first filled cell means "same as the
84
+ * row above" (Excel writes a parent only on the first row of its group).
85
+ * A blank AFTER the last filled cell ends the branch there — that cell is
86
+ * the row's leaf, so a shorter branch (`Services | Training | <blank>`)
87
+ * is a leaf of the second level, not `Services > Training > <previous
88
+ * item>` as plain per-column fill-down would make it.
89
+ */
90
+ var layoutHierarchyLevels = function (levelColumns, rowCount) {
91
+ var filled = [];
92
+ var above = levelColumns.map(function () { return ""; });
93
+ var _loop_1 = function (row) {
94
+ var cells = levelColumns.map(function (column) { var _a; return (_a = column[row]) !== null && _a !== void 0 ? _a : ""; });
95
+ var firstFilled = cells.findIndex(function (cell) { return cell !== ""; });
96
+ if (firstFilled === -1) {
97
+ // An entirely blank row defines nothing (and inherits nothing).
98
+ filled.push([]);
99
+ return "continue";
100
+ }
101
+ var effective = cells.map(function (cell, level) { var _a; return level < firstFilled ? (_a = above[level]) !== null && _a !== void 0 ? _a : "" : cell; });
102
+ var lastFilled = effective.length - 1;
103
+ while (lastFilled >= 0 && effective[lastFilled] === "")
104
+ lastFilled--;
105
+ // The row's own levels end at its last filled cell; the cells past it
106
+ // stay blank for the rows below (they inherit up to the leaf only).
107
+ above = effective.map(function (cell, level) { return (level <= lastFilled ? cell : ""); });
108
+ filled.push(effective.slice(0, lastFilled + 1).filter(function (cell) { return cell !== ""; }));
109
+ };
110
+ for (var row = 0; row < rowCount; row++) {
111
+ _loop_1(row);
112
+ }
113
+ return filled;
114
+ };
82
115
  var extractHierarchyRows = function (spec, options) {
116
+ var _a, _b;
83
117
  var getDomainValuesFromRange = options.getDomainValuesFromRange, getSeriesValuesFromRange = options.getSeriesValuesFromRange;
84
118
  var hiddenStrategy = options.hiddenDimensionStrategy;
85
119
  var skipHeaders = spec.useFirstRowAsHeaders !== false;
86
120
  var labels = flattenChartData(spec.labels, getDomainValuesFromRange, hiddenStrategy, skipHeaders).map(toLabelString);
87
- var parents = flattenChartData(spec.parentLabels, getDomainValuesFromRange, hiddenStrategy, skipHeaders);
121
+ // Each `parentLabels` entry is one hierarchy level (top level first).
122
+ var parentLevels = ((_a = spec.parentLabels) !== null && _a !== void 0 ? _a : []).map(function (entry) {
123
+ return flattenChartData([entry], getDomainValuesFromRange, hiddenStrategy, skipHeaders).map(toLabelString);
124
+ });
88
125
  var sizes = flattenChartData(spec.sizeData, getSeriesValuesFromRange, hiddenStrategy, skipHeaders);
126
+ // A single parent column whose values name other rows' labels is a flat
127
+ // adjacency list (Google Sheets' label / parent-label model): every row
128
+ // is its own node and a blank parent means a root. Excel's level layout
129
+ // never lists a level name in the label column.
130
+ var labelSet = new Set(labels.filter(function (label) { return label !== ""; }));
131
+ var isAdjacencyList = parentLevels.length === 1 &&
132
+ parentLevels[0].some(function (parent) { return parent !== "" && labelSet.has(parent); });
89
133
  var rows = [];
90
- var seenLabels = new Set();
91
- for (var i = 0; i < labels.length; i++) {
92
- var label = labels[i];
93
- if (!label)
134
+ var seenPaths = new Set();
135
+ if (isAdjacencyList) {
136
+ var parents = parentLevels[0];
137
+ for (var i = 0; i < labels.length; i++) {
138
+ var label = labels[i];
139
+ if (!label)
140
+ continue;
141
+ if (seenPaths.has(label)) {
142
+ throw new Error("Duplicate hierarchy label detected: ".concat(label));
143
+ }
144
+ seenPaths.add(label);
145
+ var parent_1 = (_b = parents[i]) !== null && _b !== void 0 ? _b : "";
146
+ rows.push({
147
+ label: label,
148
+ parent: parent_1 === "" ? null : parent_1,
149
+ value: toNumericValue(sizes[i]),
150
+ });
151
+ }
152
+ return rows;
153
+ }
154
+ var rowCount = Math.max.apply(Math, tslib_1.__spreadArray([labels.length], tslib_1.__read(parentLevels.map(function (level) { return level.length; })), false));
155
+ var levels = layoutHierarchyLevels(tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(parentLevels), false), [labels], false), rowCount);
156
+ for (var i = 0; i < rowCount; i++) {
157
+ var cells = levels[i];
158
+ if (!cells || cells.length === 0)
94
159
  continue;
95
- if (seenLabels.has(label)) {
160
+ var label = cells[cells.length - 1];
161
+ var path = cells.slice(0, -1);
162
+ var key = tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(path), false), [label], false).join("\u0000");
163
+ if (seenPaths.has(key)) {
96
164
  throw new Error("Duplicate hierarchy label detected: ".concat(label));
97
165
  }
98
- seenLabels.add(label);
166
+ seenPaths.add(key);
99
167
  rows.push({
100
168
  label: label,
101
- parent: toParentLabel(parents[i]),
169
+ parent: path.length ? path[path.length - 1] : null,
102
170
  value: toNumericValue(sizes[i]),
171
+ path: path,
103
172
  });
104
173
  }
105
174
  return rows;
106
175
  };
107
176
  exports.extractHierarchyRows = extractHierarchyRows;
108
- var getOrCreateNode = function (nodes, name) {
109
- var existing = nodes.get(name);
110
- if (existing)
111
- return existing;
112
- var node = {
113
- name: name,
114
- value: 0,
115
- parent: null,
116
- children: new Set(),
177
+ var PATH_SEPARATOR = "/";
178
+ /**
179
+ * The full path of every row, top level first, ending with the row's own
180
+ * label. A row carrying `path` (Excel's level layout) is placed under it;
181
+ * a legacy adjacency row names its parent, which is another row's label,
182
+ * so its path is that row's path plus itself (chained up to a root).
183
+ */
184
+ var resolveRowPaths = function (rows) {
185
+ var byLabel = new Map();
186
+ rows.forEach(function (row) {
187
+ if (row.label && !row.path && !byLabel.has(row.label)) {
188
+ byLabel.set(row.label, row);
189
+ }
190
+ });
191
+ var memo = new Map();
192
+ var resolve = function (row, visiting) {
193
+ var cached = memo.get(row);
194
+ if (cached)
195
+ return cached;
196
+ var path;
197
+ if (row.path) {
198
+ path = tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(row.path), false), [row.label], false);
199
+ }
200
+ else {
201
+ var parentName = row.parent && row.parent !== row.label ? row.parent : null;
202
+ var parentRow = parentName ? byLabel.get(parentName) : undefined;
203
+ if (parentRow && parentRow !== row && !visiting.has(parentRow)) {
204
+ visiting.add(row);
205
+ path = tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(resolve(parentRow, visiting)), false), [row.label], false);
206
+ visiting.delete(row);
207
+ }
208
+ else {
209
+ path = parentName ? [parentName, row.label] : [row.label];
210
+ }
211
+ }
212
+ memo.set(row, path);
213
+ return path;
117
214
  };
118
- nodes.set(name, node);
119
- return node;
215
+ return rows.map(function (row) { return resolve(row, new Set()); });
120
216
  };
121
217
  var buildHierarchyTree = function (rows) {
122
- var nodes = new Map();
123
- rows.forEach(function (row) {
218
+ var roots = new Map();
219
+ var nodeAt = function (path) {
220
+ var level = roots;
221
+ var node;
222
+ path.forEach(function (name, depth) {
223
+ var existing = level.get(name);
224
+ if (existing) {
225
+ node = existing;
226
+ }
227
+ else {
228
+ node = {
229
+ name: name,
230
+ id: path.slice(0, depth + 1).join(PATH_SEPARATOR),
231
+ value: 0,
232
+ children: new Map(),
233
+ };
234
+ level.set(name, node);
235
+ }
236
+ level = node.children;
237
+ });
238
+ return node;
239
+ };
240
+ var paths = resolveRowPaths(rows);
241
+ rows.forEach(function (row, index) {
124
242
  var _a;
125
243
  if (!row.label)
126
244
  return;
127
- var labelNode = getOrCreateNode(nodes, row.label);
128
- var numericValue = (_a = row.value) !== null && _a !== void 0 ? _a : 0;
129
- labelNode.value += numericValue;
130
- var parentName = row.parent && row.parent !== row.label ? row.parent : null;
131
- if (parentName) {
132
- var parentNode = getOrCreateNode(nodes, parentName);
133
- parentNode.children.add(row.label);
134
- if (labelNode.parent == null) {
135
- labelNode.parent = parentName;
136
- }
137
- }
245
+ var node = nodeAt(paths[index]);
246
+ node.value += (_a = row.value) !== null && _a !== void 0 ? _a : 0;
138
247
  });
139
248
  var buildNode = function (internal) {
140
249
  var children = internal.children.size > 0
141
- ? Array.from(internal.children).map(function (childName) {
142
- return buildNode(getOrCreateNode(nodes, childName));
143
- })
250
+ ? Array.from(internal.children.values()).map(buildNode)
144
251
  : undefined;
145
252
  var value = children && children.length > 0
146
253
  ? children.reduce(function (sum, child) { var _a; return sum + ((_a = child.value) !== null && _a !== void 0 ? _a : 0); }, 0)
147
254
  : internal.value;
148
255
  var node = {
149
256
  name: internal.name,
150
- id: internal.name,
257
+ id: internal.id,
151
258
  value: value,
152
259
  };
153
260
  if (children && children.length > 0) {
@@ -155,32 +262,49 @@ var buildHierarchyTree = function (rows) {
155
262
  }
156
263
  return node;
157
264
  };
158
- var roots = [];
159
- nodes.forEach(function (internal) {
160
- if (internal.parent == null) {
161
- roots.push(buildNode(internal));
162
- }
163
- });
164
- return roots;
265
+ return Array.from(roots.values()).map(buildNode);
165
266
  };
166
267
  exports.buildHierarchyTree = buildHierarchyTree;
167
268
  var toPlotlyHierarchy = function (rows) {
168
269
  var tree = (0, exports.buildHierarchyTree)(rows);
169
270
  var labels = [];
271
+ var ids = [];
170
272
  var parents = [];
171
273
  var values = [];
172
- var traverse = function (nodes, parentName) {
274
+ var depths = [];
275
+ var traverse = function (nodes, parentId, depth) {
173
276
  nodes.forEach(function (node) {
174
- var _a;
277
+ var _a, _b, _c;
175
278
  labels.push(node.name);
176
- parents.push(parentName !== null && parentName !== void 0 ? parentName : "");
177
- values.push((_a = node.value) !== null && _a !== void 0 ? _a : 0);
279
+ ids.push((_a = node.id) !== null && _a !== void 0 ? _a : node.name);
280
+ parents.push(parentId);
281
+ values.push((_b = node.value) !== null && _b !== void 0 ? _b : 0);
282
+ depths.push(depth);
178
283
  if (node.children) {
179
- traverse(node.children, node.name);
284
+ traverse(node.children, (_c = node.id) !== null && _c !== void 0 ? _c : node.name, depth + 1);
180
285
  }
181
286
  });
182
287
  };
183
- traverse(tree, null);
184
- return { labels: labels, parents: parents, values: values };
288
+ traverse(tree, "", 0);
289
+ return { labels: labels, ids: ids, parents: parents, values: values, depths: depths };
185
290
  };
186
291
  exports.toPlotlyHierarchy = toPlotlyHierarchy;
292
+ /**
293
+ * One solid colour per top-level category, inherited by every descendant
294
+ * (Excel colours a treemap / sunburst by its first level), in tree order.
295
+ * Returns the colour per node of `toPlotlyHierarchy`'s flat arrays.
296
+ */
297
+ var hierarchyNodeColors = function (hierarchy, palette) {
298
+ var colorById = new Map();
299
+ var rootIndex = 0;
300
+ return hierarchy.ids.map(function (id, index) {
301
+ var _a, _b;
302
+ var parentId = hierarchy.parents[index];
303
+ var color = parentId === ""
304
+ ? (_a = palette[rootIndex++ % Math.max(1, palette.length)]) !== null && _a !== void 0 ? _a : ""
305
+ : (_b = colorById.get(parentId)) !== null && _b !== void 0 ? _b : "";
306
+ colorById.set(id, color);
307
+ return color;
308
+ });
309
+ };
310
+ exports.hierarchyNodeColors = hierarchyNodeColors;
@@ -1 +1 @@
1
- {"version":3,"file":"overrides.d.ts","sourceRoot":"","sources":["../../../utils/overrides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAWrD,oEAAoE;AACpE,eAAO,MAAM,4BAA4B,GAAI,KAAK,GAAG,oCASpD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,qBAAqB,EAC7B,MAAM,GAAG,KACR,qBA6CF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,GAAG,EACT,MAAM,GAAG,EACT,sBAAsB,MAAM,EAC5B,SAAS,MAAM,QA4BhB,CAAC;AAgBF,eAAO,MAAM,kBAAkB,GAAI,MAAM,GAAG,EAAE,SAAS,MAAM,MAAM,QAAQ,GAAG,WAiC7E,CAAC;AAgCF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,CAAC,EACvC,YAAY,CAAC,GAAG,IAAI,GAAG,SAAS,EAChC,QAAQ;IAAE,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,KACnD,CAAC,GAAG,IAAI,GAAG,SAA6C,CAAC;AAE5D,eAAO,MAAM,sBAAsB,GACjC,MAAM,GAAG,EACT,aAAa,MAAM,EACnB,SAAS,MAAM;;;iCA/E0D,GAAG;aA4F7E,CAAC"}
1
+ {"version":3,"file":"overrides.d.ts","sourceRoot":"","sources":["../../../utils/overrides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAWrD,oEAAoE;AACpE,eAAO,MAAM,4BAA4B,GAAI,KAAK,GAAG,oCASpD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,qBAAqB,EAC7B,MAAM,GAAG,KACR,qBA6CF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,GAAG,EACT,MAAM,GAAG,EACT,sBAAsB,MAAM,EAC5B,SAAS,MAAM,QA4BhB,CAAC;AAgBF,eAAO,MAAM,kBAAkB,GAAI,MAAM,GAAG,EAAE,SAAS,MAAM,MAAM,QAAQ,GAAG,WAoD7E,CAAC;AAgCF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,CAAC,EACvC,YAAY,CAAC,GAAG,IAAI,GAAG,SAAS,EAChC,QAAQ;IAAE,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,KACnD,CAAC,GAAG,IAAI,GAAG,SAA6C,CAAC;AAE5D,eAAO,MAAM,sBAAsB,GACjC,MAAM,GAAG,EACT,aAAa,MAAM,EACnB,SAAS,MAAM;;;iCAlG0D,GAAG;aA+G7E,CAAC"}
@@ -135,13 +135,22 @@ var dataLabelFormatter = function (opts, locale) { return function (params) {
135
135
  if (opts.showPercent && params.percent !== undefined) {
136
136
  parts.push("".concat(params.percent, "%"));
137
137
  }
138
+ // The value shows by default unless another field was asked for instead:
139
+ // an importer records only the flags that are ON, so `<c:showVal val="0"/>`
140
+ // + `<c:showBubbleSize val="1"/>` arrives as `{ showBubbleSize: true }` and
141
+ // must label the bubble with its size alone (#1068 / #1079).
138
142
  var showVal = opts.showValue !== false &&
139
143
  !opts.showCategoryName &&
140
144
  !opts.showPercent &&
141
- !opts.showSeriesName
145
+ !opts.showSeriesName &&
146
+ !opts.showBubbleSize
142
147
  ? true
143
148
  : !!opts.showValue;
144
- if (showVal && params.value !== undefined) {
149
+ // A scatter / bubble point's value is its [x, y, size] tuple: the label's
150
+ // value is Y and the bubble size is the third entry (#1068).
151
+ var isPointTuple = Array.isArray(params.value);
152
+ var pointValue = isPointTuple ? params.value[1] : params.value;
153
+ if (showVal && pointValue !== undefined) {
145
154
  // PERCENT_STACKED stores the raw value on the data object so the
146
155
  // label can still surface the dollar amount instead of the
147
156
  // normalized percentage. Plain stacked / clustered have just a
@@ -149,7 +158,10 @@ var dataLabelFormatter = function (opts, locale) { return function (params) {
149
158
  var originalValue = typeof params.data === "object" && params.data
150
159
  ? params.data.originalValue
151
160
  : undefined;
152
- parts.push(formatLabelValue(params.value, originalValue, opts.numberFormatPattern, locale));
161
+ parts.push(formatLabelValue(pointValue, originalValue, opts.numberFormatPattern, locale));
162
+ }
163
+ if (opts.showBubbleSize && isPointTuple && params.value.length > 2) {
164
+ parts.push(formatLabelValue(params.value[2], undefined, opts.numberFormatPattern, locale));
153
165
  }
154
166
  return parts.join(": ");
155
167
  }; };
@@ -43,6 +43,12 @@ export type TrendlineResult = {
43
43
  * @param values Raw y-values; the 1-based category position is used as x
44
44
  * for the fit, the 0-based index is reported in the points.
45
45
  * @param spec Trendline parameters (type/order/period/forecast).
46
+ * @param xValues Scatter / bubble only — the series' real X values, index-
47
+ * aligned with `values`. The fit then runs on (x, y) pairs
48
+ * (a regression of Y on X, what Excel draws on an XY chart;
49
+ * the point index is wrong for unevenly spaced X), the
50
+ * forecast extends the X range by that many X units, and the
51
+ * points carry real X coordinates sampled across the range.
46
52
  */
47
53
  export declare const computeTrendline: (values: (number | null | undefined)[], spec?: {
48
54
  type?: TrendlineType | null;
@@ -50,5 +56,5 @@ export declare const computeTrendline: (values: (number | null | undefined)[], s
50
56
  period?: number | null;
51
57
  forecastForward?: number | null;
52
58
  forecastBackward?: number | null;
53
- }) => TrendlineResult | null;
59
+ }, xValues?: (number | null | undefined)[] | null) => TrendlineResult | null;
54
60
  //# sourceMappingURL=trendline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trendline.d.ts","sourceRoot":"","sources":["../../../utils/trendline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,aAAa,GACrB,QAAQ,GACR,KAAK,GACL,KAAK,GACL,MAAM,GACN,OAAO,GACP,WAAW,CAAC;AAEhB,6FAA6F;AAC7F,MAAM,MAAM,cAAc,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,eAAe,GAAG;IAC5B,sEAAsE;IACtE,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAsJF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EACrC,OAAM;IACJ,IAAI,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,KACL,eAAe,GAAG,IAiGpB,CAAC"}
1
+ {"version":3,"file":"trendline.d.ts","sourceRoot":"","sources":["../../../utils/trendline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,aAAa,GACrB,QAAQ,GACR,KAAK,GACL,KAAK,GACL,MAAM,GACN,OAAO,GACP,WAAW,CAAC;AAEhB,6FAA6F;AAC7F,MAAM,MAAM,cAAc,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,eAAe,GAAG;IAC5B,sEAAsE;IACtE,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAkKF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EACrC,OAAM;IACJ,IAAI,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,EACN,UAAU,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,KAC7C,eAAe,GAAG,IA+HpB,CAAC"}
@@ -35,15 +35,25 @@ var isFiniteNum = function (v) {
35
35
  * position as x (the first category is x = 1, see the module comment).
36
36
  * Non-finite y-values are dropped (they cannot be fitted).
37
37
  */
38
- var toPairs = function (values) {
38
+ var toPairs = function (values, xValues) {
39
39
  var pairs = [];
40
40
  for (var i = 0; i < values.length; i++) {
41
41
  var y = values[i];
42
- if (isFiniteNum(y))
42
+ if (!isFiniteNum(y))
43
+ continue;
44
+ if (xValues) {
45
+ var x = xValues[i];
46
+ if (isFiniteNum(x))
47
+ pairs.push({ x: x, y: y });
48
+ }
49
+ else {
43
50
  pairs.push({ x: i + 1, y: y });
51
+ }
44
52
  }
45
53
  return pairs;
46
54
  };
55
+ /** Samples along a scatter trendline's x range: enough for the curved fits to read as curves. */
56
+ var XY_TRENDLINE_SAMPLES = 64;
47
57
  /** Compute R² between observed y and predicted f(x) over the fit pairs. */
48
58
  var rSquaredOf = function (pairs, predict) {
49
59
  var e_1, _a;
@@ -218,20 +228,29 @@ var fitPower = function (pairs) {
218
228
  * @param values Raw y-values; the 1-based category position is used as x
219
229
  * for the fit, the 0-based index is reported in the points.
220
230
  * @param spec Trendline parameters (type/order/period/forecast).
231
+ * @param xValues Scatter / bubble only — the series' real X values, index-
232
+ * aligned with `values`. The fit then runs on (x, y) pairs
233
+ * (a regression of Y on X, what Excel draws on an XY chart;
234
+ * the point index is wrong for unevenly spaced X), the
235
+ * forecast extends the X range by that many X units, and the
236
+ * points carry real X coordinates sampled across the range.
221
237
  */
222
- var computeTrendline = function (values, spec) {
223
- var _a, _b, _c, _d, _e;
238
+ var computeTrendline = function (values, spec, xValues) {
239
+ var e_4, _a;
240
+ var _b, _c, _d, _e, _f;
224
241
  if (spec === void 0) { spec = {}; }
225
- var pairs = toPairs(values);
242
+ var pairs = toPairs(values, xValues);
226
243
  if (pairs.length < 2)
227
244
  return null;
228
- var type = (_a = spec.type) !== null && _a !== void 0 ? _a : "linear";
229
- var forward = Math.max(0, Math.floor((_b = spec.forecastForward) !== null && _b !== void 0 ? _b : 0));
230
- var backward = Math.max(0, Math.floor((_c = spec.forecastBackward) !== null && _c !== void 0 ? _c : 0));
245
+ var type = (_b = spec.type) !== null && _b !== void 0 ? _b : "linear";
246
+ var forwardRaw = Math.max(0, (_c = spec.forecastForward) !== null && _c !== void 0 ? _c : 0);
247
+ var backwardRaw = Math.max(0, (_d = spec.forecastBackward) !== null && _d !== void 0 ? _d : 0);
248
+ var forward = xValues ? forwardRaw : Math.floor(forwardRaw);
249
+ var backward = xValues ? backwardRaw : Math.floor(backwardRaw);
231
250
  // Moving average is a smoothing of the observed values, not a fitted
232
251
  // function, so it is handled separately and ignores forecasting.
233
252
  if (type === "movingAvg") {
234
- var period = Math.max(2, Math.floor((_d = spec.period) !== null && _d !== void 0 ? _d : 2));
253
+ var period = Math.max(2, Math.floor((_e = spec.period) !== null && _e !== void 0 ? _e : 2));
235
254
  var points_1 = [];
236
255
  for (var i = period - 1; i < values.length; i++) {
237
256
  var sum = 0;
@@ -243,17 +262,61 @@ var computeTrendline = function (values, spec) {
243
262
  count++;
244
263
  }
245
264
  }
246
- if (count > 0)
265
+ if (count === 0)
266
+ continue;
267
+ if (xValues) {
268
+ var x = xValues[i];
269
+ if (isFiniteNum(x))
270
+ points_1.push({ x: x, y: sum / count });
271
+ }
272
+ else {
247
273
  points_1.push({ x: i, y: sum / count });
274
+ }
248
275
  }
276
+ if (xValues)
277
+ points_1.sort(function (a, b) { return a.x - b.x; });
249
278
  return { points: points_1, rSquared: null, equation: null };
250
279
  }
251
- // Fit domain is 1..n; a forecast of k periods extends it to 1−k / n+k.
252
- var xStart = 1 - backward;
253
- var xEnd = values.length + forward;
254
280
  var xs = [];
255
- for (var x = xStart; x <= xEnd; x++)
256
- xs.push(x);
281
+ if (xValues) {
282
+ // Sample the fitted curve across the data's X range, extended by the
283
+ // forecast in X units.
284
+ var minX = Infinity;
285
+ var maxX = -Infinity;
286
+ try {
287
+ for (var pairs_4 = tslib_1.__values(pairs), pairs_4_1 = pairs_4.next(); !pairs_4_1.done; pairs_4_1 = pairs_4.next()) {
288
+ var p = pairs_4_1.value;
289
+ if (p.x < minX)
290
+ minX = p.x;
291
+ if (p.x > maxX)
292
+ maxX = p.x;
293
+ }
294
+ }
295
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
296
+ finally {
297
+ try {
298
+ if (pairs_4_1 && !pairs_4_1.done && (_a = pairs_4.return)) _a.call(pairs_4);
299
+ }
300
+ finally { if (e_4) throw e_4.error; }
301
+ }
302
+ var xStart = minX - backward;
303
+ var xEnd = maxX + forward;
304
+ if (xEnd > xStart) {
305
+ for (var i = 0; i <= XY_TRENDLINE_SAMPLES; i++) {
306
+ xs.push(xStart + ((xEnd - xStart) * i) / XY_TRENDLINE_SAMPLES);
307
+ }
308
+ }
309
+ else {
310
+ xs.push(xStart);
311
+ }
312
+ }
313
+ else {
314
+ // Fit domain is 1..n; a forecast of k periods extends it to 1−k / n+k.
315
+ var xStart = 1 - backward;
316
+ var xEnd = values.length + forward;
317
+ for (var x = xStart; x <= xEnd; x++)
318
+ xs.push(x);
319
+ }
257
320
  var predict = null;
258
321
  var equation = null;
259
322
  switch (type) {
@@ -266,7 +329,7 @@ var computeTrendline = function (values, spec) {
266
329
  break;
267
330
  }
268
331
  case "poly": {
269
- var coeffs_1 = fitPoly(pairs, (_e = spec.order) !== null && _e !== void 0 ? _e : 2);
332
+ var coeffs_1 = fitPoly(pairs, (_f = spec.order) !== null && _f !== void 0 ? _f : 2);
270
333
  if (!coeffs_1)
271
334
  return null;
272
335
  predict = function (x) {
@@ -310,9 +373,10 @@ var computeTrendline = function (values, spec) {
310
373
  default:
311
374
  return null;
312
375
  }
313
- // Report the renderer-facing 0-based category index (see module comment).
376
+ // Report the renderer-facing 0-based category index (see module comment);
377
+ // an XY fit reports the real X it was sampled at.
314
378
  var points = xs
315
- .map(function (x) { return ({ x: x - 1, y: predict(x) }); })
379
+ .map(function (x) { return ({ x: xValues ? x : x - 1, y: predict(x) }); })
316
380
  .filter(function (p) { return Number.isFinite(p.y); });
317
381
  if (points.length < 2)
318
382
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"basic-chart.d.ts","sourceRoot":"","sources":["../../../basic-chart/basic-chart.tsx"],"names":[],"mappings":"AAkEA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAqQrD,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAqEnD,eAAO,MAAM,UAAU,GAAI,gPAkBxB,eAAe,sBAq6GjB,CAAC"}
1
+ {"version":3,"file":"basic-chart.d.ts","sourceRoot":"","sources":["../../../basic-chart/basic-chart.tsx"],"names":[],"mappings":"AAkEA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAkSrD,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAiGnD,eAAO,MAAM,UAAU,GAAI,gPAkBxB,eAAe,sBAkgHjB,CAAC"}