@hpcc-js/chart 3.7.4 → 3.7.5

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 (80) hide show
  1. package/LICENSE +43 -43
  2. package/README.md +93 -93
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.umd.cjs +1 -1
  6. package/dist/index.umd.cjs.map +1 -1
  7. package/package.json +5 -5
  8. package/src/Area.md +176 -176
  9. package/src/Area.ts +12 -12
  10. package/src/Axis.css +35 -35
  11. package/src/Axis.ts +781 -781
  12. package/src/Bar.md +90 -90
  13. package/src/Bar.ts +9 -9
  14. package/src/Bubble.css +16 -16
  15. package/src/Bubble.md +69 -69
  16. package/src/Bubble.ts +196 -196
  17. package/src/BubbleXY.ts +14 -14
  18. package/src/Bullet.css +59 -59
  19. package/src/Bullet.md +104 -104
  20. package/src/Bullet.ts +176 -176
  21. package/src/Column.css +44 -44
  22. package/src/Column.md +90 -90
  23. package/src/Column.ts +684 -684
  24. package/src/Contour.md +88 -88
  25. package/src/Contour.ts +97 -97
  26. package/src/D3Cloud.ts +403 -403
  27. package/src/Gantt.md +119 -119
  28. package/src/Gantt.ts +14 -14
  29. package/src/Gauge.md +148 -148
  30. package/src/Gauge.ts +368 -368
  31. package/src/HalfPie.md +62 -62
  32. package/src/HalfPie.ts +26 -26
  33. package/src/Heat.md +42 -42
  34. package/src/Heat.ts +283 -283
  35. package/src/HexBin.css +8 -8
  36. package/src/HexBin.md +88 -88
  37. package/src/HexBin.ts +144 -144
  38. package/src/Line.css +4 -4
  39. package/src/Line.md +170 -170
  40. package/src/Line.ts +14 -14
  41. package/src/Pie.css +50 -50
  42. package/src/Pie.md +88 -88
  43. package/src/Pie.ts +546 -546
  44. package/src/QuarterPie.md +61 -61
  45. package/src/QuarterPie.ts +35 -35
  46. package/src/QuartileCandlestick.md +129 -129
  47. package/src/QuartileCandlestick.ts +349 -349
  48. package/src/Radar.css +14 -14
  49. package/src/Radar.md +104 -104
  50. package/src/Radar.ts +336 -336
  51. package/src/RadialBar.css +25 -25
  52. package/src/RadialBar.md +91 -91
  53. package/src/RadialBar.ts +217 -217
  54. package/src/Scatter.css +42 -42
  55. package/src/Scatter.md +163 -163
  56. package/src/Scatter.ts +412 -412
  57. package/src/StatChart.md +117 -117
  58. package/src/StatChart.ts +261 -261
  59. package/src/Step.md +163 -163
  60. package/src/Step.ts +12 -12
  61. package/src/Summary.css +55 -55
  62. package/src/Summary.md +219 -219
  63. package/src/Summary.ts +322 -322
  64. package/src/SummaryC.md +154 -154
  65. package/src/SummaryC.ts +240 -240
  66. package/src/WordCloud.css +2 -2
  67. package/src/WordCloud.md +144 -144
  68. package/src/WordCloud.ts +268 -268
  69. package/src/XYAxis.css +40 -40
  70. package/src/XYAxis.md +149 -149
  71. package/src/XYAxis.ts +809 -809
  72. package/src/__package__.ts +3 -3
  73. package/src/__tests__/heat.ts +71 -71
  74. package/src/__tests__/index.ts +3 -3
  75. package/src/__tests__/pie.ts +20 -20
  76. package/src/__tests__/stat.ts +16 -16
  77. package/src/__tests__/test3.ts +68 -68
  78. package/src/index.ts +28 -28
  79. package/src/test.ts +70 -70
  80. package/src/timeFormats.ts +26 -26
package/src/Scatter.ts CHANGED
@@ -1,412 +1,412 @@
1
- import { INDChart, ITooltip } from "@hpcc-js/api";
2
- import { d3Event, InputField } from "@hpcc-js/common";
3
- import { extent as d3Extent } from "d3-array";
4
- import { scaleLinear as d3ScaleLinear, scaleLog as d3ScaleLog, scalePow as d3ScalePow, scaleSqrt as d3ScaleSqrt } from "d3-scale";
5
- import { select as d3Select } from "d3-selection";
6
- import {
7
- area as d3Area,
8
- curveBasis as d3CurveBasis, curveBundle as d3CurveBundle, curveCardinal as d3CurveCardinal, curveCatmullRom as d3curveCatmullRom, curveLinear as d3CurveLinear,
9
- curveMonotoneX as d3CurveMonotoneX, curveNatural as d3CurveNatural, curveStep as d3CurveStep, curveStepAfter as d3CurveStepAfter, curveStepBefore as d3CurveStepBefore,
10
- line as d3Line
11
- } from "d3-shape";
12
- import { XYAxis } from "./XYAxis.ts";
13
-
14
- import "../src/Scatter.css";
15
-
16
- export class Scatter extends XYAxis {
17
- static __inputs: InputField[] = [{
18
- id: "label",
19
- type: "any"
20
- }, {
21
- id: "values",
22
- type: "number",
23
- multi: true
24
- }];
25
-
26
- constructor() {
27
- super();
28
- INDChart.call(this);
29
- ITooltip.call(this);
30
- this
31
- .xAxisGuideLines_default(true)
32
- .yAxisGuideLines_default(true)
33
- ;
34
- }
35
-
36
- xPos(host: XYAxis, d) {
37
- return host.orientation() === "horizontal" ? host.dataPos(d.label) : host.valuePos(d.value);
38
- }
39
-
40
- yPos(host: XYAxis, d) {
41
- return host.orientation() === "horizontal" ? host.valuePos(d.value) : host.dataPos(d.label);
42
- }
43
-
44
- private curve(): any {
45
- switch (this.interpolate()) {
46
- case "linear":
47
- return d3CurveLinear;
48
- case "step":
49
- return d3CurveStep;
50
- case "step-before":
51
- return d3CurveStepBefore;
52
- case "step-after":
53
- return d3CurveStepAfter;
54
- case "basis":
55
- return d3CurveBasis;
56
- case "bundle":
57
- return d3CurveBundle;
58
- case "cardinal":
59
- return d3CurveCardinal;
60
- case "catmullRom":
61
- return d3curveCatmullRom;
62
- case "natural":
63
- return d3CurveNatural;
64
- case "monotone":
65
- default:
66
- return d3CurveMonotoneX;
67
- }
68
- }
69
-
70
- private getScale() {
71
- switch (this.pointSizeScale()) {
72
- case "linear":
73
- return d3ScaleLinear();
74
- case "pow":
75
- return d3ScalePow().exponent(2);
76
- case "log":
77
- return d3ScaleLog();
78
- case "sqrt":
79
- return d3ScaleSqrt();
80
- }
81
- }
82
-
83
- protected pointColor(row, col, value, origRow) {
84
- if (this.interpolate() && this.pointDarken()) {
85
- return this.strokeColor(row, col, value, origRow);
86
- }
87
- return this.fillColor(row, col, value, origRow);
88
- }
89
-
90
- protected lineColor(row, col, value, origRow) {
91
- if (this.interpolateFill() && this.interpolateDarken()) {
92
- return this.strokeColor(row, col, value, origRow);
93
- }
94
- return this.fillColor(row, col, value, origRow);
95
- }
96
-
97
- protected areaColor(row, col, value, origRow) {
98
- return this.fillColor(row, col, value, origRow);
99
- }
100
-
101
- layerEnter(host: XYAxis, element, duration: number = 250) {
102
- super.layerEnter(host, element, duration);
103
- const context = this;
104
- this
105
- .tooltipHTML(function (d) {
106
- switch (context.tooltipStyle()) {
107
- case "series-table":
108
- return context.tooltipFormat({
109
- label: d.label,
110
- arr: context.columns().slice(1).map(function (column, i) {
111
- return {
112
- label: column,
113
- color: context._palette(column),
114
- value: context.data()[d.rowIdx][i + 1]
115
- };
116
- })
117
- });
118
- default:
119
- return context.tooltipFormat({ label: d.label, series: d.column, value: d.value });
120
- }
121
- })
122
- ;
123
- }
124
-
125
- protected _prevPointShape;
126
- layerUpdate(host: XYAxis, element, duration: number = 250) {
127
- super.layerUpdate(host, element);
128
- const isHorizontal = host.orientation() === "horizontal";
129
- const height = isHorizontal ? this.height() : this.width();
130
- const context = this;
131
-
132
- if (this.tabNavigation() && host.parentRelativeDiv) {
133
- host.parentRelativeDiv
134
- .attr("tabindex", "0")
135
- .attr("role", "group")
136
- .attr("aria-label", `${this.columns()[0] || "Chart"} data`);
137
- } else if (host.parentRelativeDiv) {
138
- host.parentRelativeDiv
139
- .attr("tabindex", null)
140
- .attr("role", null)
141
- .attr("aria-label", null);
142
- }
143
-
144
- this._palette = this._palette.switch(this.paletteID());
145
- if (this.useClonedPalette()) {
146
- this._palette = this._palette.cloneNotExists(this.paletteID() + "_" + this.id());
147
- }
148
-
149
- if (this._prevPointShape !== this.pointShape()) {
150
- element.selectAll(".data").remove();
151
- this._prevPointShape = this.pointShape();
152
- }
153
-
154
- function mapShape(shape) {
155
- switch (shape) {
156
- case "rectangle":
157
- return "rect";
158
- case "circle":
159
- return "circle";
160
- case "cross":
161
- return "path";
162
- default:
163
- }
164
- }
165
- const usePointSizeColumn = this.pointSizeColumn_exists();
166
- let pointSizeColumnIdx;
167
- let extent;
168
- let scale;
169
- if (usePointSizeColumn) {
170
- pointSizeColumnIdx = this.columns().indexOf(this.pointSizeColumn());
171
- extent = d3Extent(this.data(), d => d[pointSizeColumnIdx]);
172
- scale = this.getScale().domain(extent);
173
- }
174
- const layerColumns = this.layerColumns(host);
175
- const layerData = this.layerData(host);
176
- const flatData = this.flattenData(layerColumns, layerData).map(function (d) {
177
- d.shape = mapShape(context.pointShape());
178
- d.column = layerColumns[d.colIdx];
179
- d.row = layerData[d.rowIdx];
180
- d.origRow = (layerData[d.rowIdx] as any).__hpcc_origRow;
181
- if (extent) {
182
- d.size = scale(d.row[pointSizeColumnIdx]) * (context.maxPointSize() - context.minPointSize()) + context.minPointSize();
183
- return d.column === context.pointSizeColumn() ? false : d;
184
- } else {
185
- d.size = context.pointSize();
186
- return d;
187
- }
188
-
189
- }).filter(d => d);
190
-
191
- const areas = element.selectAll(".area").data(layerColumns.filter(function (_d, idx) { return context.interpolate() && context.interpolateFill() && idx > 0; }));
192
- const areasEnter = areas.enter().append("path");
193
- const area = d3Area()
194
- .curve(this.curve())
195
- ;
196
- if (isHorizontal) {
197
- area
198
- .x(function (d) { return context.xPos(host, d); })
199
- .y0(Math.min(height, this.yPos(host, { value: 0 })))
200
- .y1(function (d) { return context.yPos(host, d); })
201
- ;
202
- } else {
203
- area
204
- .y(function (d) { return context.yPos(host, d); })
205
- .x0(Math.max(0, this.xPos(host, { value: 0 })))
206
- .x1(function (d) { return context.xPos(host, d); })
207
- ;
208
- }
209
- areasEnter.merge(areas)
210
- .attr("class", d => "area series series-" + this.cssTag(d))
211
- .each(function (_d, idx) {
212
- const element = d3Select(this);
213
- element
214
- .attr("d", area(flatData.filter(function (d2) { return d2.colIdx === idx + 1; })))
215
- .style("opacity", context.interpolateFillOpacity())
216
- .style("stroke", "none")
217
- .style("fill", context.areaColor([], _d, undefined, []))
218
- ;
219
- });
220
- areas.exit().remove();
221
-
222
- const lines = element.selectAll(".line").data(layerColumns.filter(function (_d, idx) { return context.interpolate() && idx > 0; }));
223
- const linesEnter = lines.enter().append("path");
224
- const line = d3Line()
225
- .x(function (d) { return context.xPos(host, d); })
226
- .y(function (d) { return context.yPos(host, d); })
227
- .curve(this.curve())
228
- ;
229
- linesEnter.merge(lines)
230
- .attr("class", d => "line series series-" + this.cssTag(d))
231
- .each(function (_d, idx) {
232
- const element = d3Select(this);
233
- const data2 = flatData.filter(function (d2) { return d2.colIdx === idx + 1; });
234
- element
235
- .attr("d", line(data2))
236
- .style("stroke", context.lineColor([], _d, undefined, []))
237
- .style("fill", "none")
238
- ;
239
- });
240
- lines.exit().remove();
241
-
242
- const points = element.selectAll(".point").data(flatData, function (d, idx) { return d.shape + "_" + idx; });
243
- points.enter().append("g")
244
- .each(function (this: SVGElement, d2) {
245
- const element = d3Select(this);
246
- element
247
- .append(d2.shape)
248
- .attr("class", "pointShape")
249
- ;
250
- element
251
- .append("text")
252
- .attr("class", "pointValue")
253
- .style("display", "none")
254
- .attr("text-anchor", context.valueAnchor())
255
- .attr("alignment-baseline", context.valueBaseline())
256
- .attr("fill", function (d: any, _idx) {
257
- const useTextColor = context.valueBaseline() === "middle" || context.valueBaseline() === "central";
258
- return useTextColor ? context.textColor(d.row, d.column, d.value, d.origRow) : null;
259
- })
260
- ;
261
- element
262
- .append("circle")
263
- .attr("class", "pointSelection")
264
- .on("mouseout.tooltip", context.tooltip.hide)
265
- .on("mousemove.tooltip", context.tooltip.show)
266
- .call(host._selection.enter.bind(host._selection))
267
- .on("click", function (d: any, _idx) {
268
- context.click(host.rowToObj(host.data()[d.rowIdx]), d.column, host._selection.selected(this));
269
- })
270
- .on("dblclick", function (d: any, _idx) {
271
- context.dblclick(host.rowToObj(host.data()[d.rowIdx]), d.column, host._selection.selected(this));
272
- })
273
- .on("keydown", function (evt, d: any) {
274
- if (context.tabNavigation()) {
275
- const event = d3Event();
276
- if (event.code === "Space" || event.key === "Enter") {
277
- event.preventDefault();
278
- host._selection.click(this);
279
- }
280
- }
281
- })
282
- ;
283
- })
284
- .merge(points)
285
- .attr("class", d => "point series series-" + this.cssTag(d.column))
286
- .each(function (this: SVGElement, d2) {
287
- const textSelection = d3Select(this).select(".pointValue");
288
- textSelection
289
- .attr("x", function (d) { return context.xPos(host, d); })
290
- .attr("y", function (d) { return context.yPos(host, d); })
291
- .style("display", context.showValue() ? "block" : "none")
292
- .attr("text-anchor", context.valueAnchor())
293
- .attr("alignment-baseline", context.valueBaseline())
294
- .text(function (d) {
295
- return d["value"];
296
- })
297
- ;
298
- const elementSelection = d3Select(this).select(".pointSelection");
299
- elementSelection
300
- .attr("cx", function (d) { return context.xPos(host, d); })
301
- .attr("cy", function (d) { return context.yPos(host, d); })
302
- .attr("r", d2.size)
303
- .attr("tabindex", context.tabNavigation() ? 0 : null)
304
- .attr("role", context.tabNavigation() ? "button" : null)
305
- .attr("aria-label", context.tabNavigation() ? (d: any) => `${d.column || "Value"}: ${d.value} @ ${d.label}` : null)
306
- ;
307
-
308
- const element = d3Select(this).select(".pointShape");
309
- switch (d2.shape) {
310
- case "rect":
311
- element
312
- .attr("x", function (d) { return context.xPos(host, d) - d2.size / 2; })
313
- .attr("y", function (d) { return context.yPos(host, d) - d2.size / 2; })
314
- .attr("width", d2.size)
315
- .attr("height", d2.size)
316
- .style("fill", context.pointColor(d2.row, d2.column, d2.value, d2.origRow))
317
- ;
318
- break;
319
- case "circle":
320
- element
321
- .attr("cx", function (d) { return context.xPos(host, d); })
322
- .attr("cy", function (d) { return context.yPos(host, d); })
323
- .attr("r", d2.size * 0.9)
324
- .style("fill", context.pointColor(d2.row, d2.column, d2.value, d2.origRow))
325
- ;
326
- break;
327
- case "path":
328
- element
329
- .attr("d", function (d: any) {
330
- return "M" + (context.xPos(host, d) - d2.size / 2) + " " + (context.yPos(host, d) - d2.size / 2) + " " +
331
- "L" + (context.xPos(host, d) + d2.size / 2) + " " + (context.yPos(host, d) + d2.size / 2) + " " +
332
- "M" + (context.xPos(host, d) - d2.size / 2) + " " + (context.yPos(host, d) + d2.size / 2) + " " +
333
- "L" + (context.xPos(host, d) + d2.size / 2) + " " + (context.yPos(host, d) - d2.size / 2);
334
- })
335
- .style("stroke", context.pointColor(d2.row, d2.column, d2.value, d2.origRow))
336
- ;
337
- break;
338
- default:
339
- }
340
- })
341
- ;
342
- points.exit().remove();
343
- }
344
-
345
- exit(domNode, element) {
346
- super.exit(domNode, element);
347
- }
348
- }
349
- Scatter.prototype._class += " chart_Scatter";
350
- Scatter.prototype.implements(INDChart.prototype);
351
- Scatter.prototype.implements(ITooltip.prototype);
352
-
353
- export interface Scatter {
354
-
355
- valueAnchor(): string;
356
- valueAnchor(_: string): this;
357
- valueBaseline(): string;
358
- valueBaseline(_: string): this;
359
- showValue(): boolean;
360
- showValue(_: boolean): this;
361
- pointDarken(): boolean;
362
- pointDarken(_: boolean): this;
363
- interpolateDarken(): boolean;
364
- interpolateDarken(_: boolean): this;
365
-
366
- paletteID(): string;
367
- paletteID(_: string): this;
368
- useClonedPalette(): boolean;
369
- useClonedPalette(_: boolean): this;
370
- pointSizeScale(): string;
371
- pointSizeScale(_: string): this;
372
- pointShape(): string;
373
- pointShape(_: string): this;
374
- pointSize(): number;
375
- pointSize(_: number): this;
376
- interpolate(): string;
377
- interpolate(_: string): this;
378
- interpolate_default(): string;
379
- interpolate_default(_: string): this;
380
- interpolateFill(): boolean;
381
- interpolateFill(_: boolean): this;
382
- interpolateFill_default(): boolean;
383
- interpolateFill_default(_: boolean): this;
384
- interpolateFillOpacity(): number;
385
- interpolateFillOpacity(_: number): this;
386
-
387
- // INDChart
388
- fillColor(row, column, value, origRow): string;
389
- strokeColor(row, column, value, origRow): string;
390
- textColor(row, column, value, origRow): string;
391
- dblclick(row, column, selected): void;
392
-
393
- // ITooltip
394
- tooltip;
395
- tooltipHTML(_): string;
396
- tooltipFormat(_): string;
397
- tooltipStyle(): "default" | "none" | "series-table";
398
- tooltipStyle(_: "default" | "none" | "series-table"): this;
399
- }
400
- Scatter.prototype.publish("paletteID", "default", "set", "Color palette for this widget", Scatter.prototype._palette.switch(), { tags: ["Basic", "Shared"] });
401
- Scatter.prototype.publish("pointSizeScale", "linear", "set", "pointSizeScale", ["linear", "pow", "log", "sqrt"]);
402
- Scatter.prototype.publish("pointShape", "cross", "set", "Shape of the data points", ["circle", "rectangle", "cross"]);
403
- Scatter.prototype.publish("pointSize", 6, "number", "Point Size", null, { range: { min: 1, step: 1, max: 200 } });
404
- Scatter.prototype.publish("interpolate", "", "set", "Interpolate Data", ["", "linear", "step", "step-before", "step-after", "basis", "bundle", "cardinal", "catmullRom", "natural", "monotone"]);
405
- Scatter.prototype.publish("pointDarken", true, "boolean", "If true, and interpolate is set, then points will have a slightly darker color than their assigned palette color", null, { disable: w => !w.interpolate() });
406
- Scatter.prototype.publish("interpolateDarken", true, "boolean", "If true, and interpolateFill is true, then lines will have a slightly darker color than their assigned palette color", null, { disable: w => !w.interpolateFill() });
407
- Scatter.prototype.publish("interpolateFill", false, "boolean", "If true, the area between the line and zero will be filled");
408
- Scatter.prototype.publish("interpolateFillOpacity", 0.66, "number", "Fill interpolation Opacity", null, { range: { min: 0, step: 0.01, max: 1 } });
409
- Scatter.prototype.publish("useClonedPalette", false, "boolean", "Enable or disable using a cloned palette", null, { tags: ["Intermediate", "Shared"] });
410
- Scatter.prototype.publish("showValue", false, "boolean");
411
- Scatter.prototype.publish("valueAnchor", "middle", "set", "text-anchor for shown value text", ["start", "middle", "end"]);
412
- Scatter.prototype.publish("valueBaseline", "ideographic", "set", "alignment-baseline for shown value text", ["auto", "baseline", "before-edge", "text-before-edge", "middle", "central", "after-edge", "text-after-edge", "ideographic", "alphabetic", "hanging", "mathematical", "inherit"]);
1
+ import { INDChart, ITooltip } from "@hpcc-js/api";
2
+ import { d3Event, InputField } from "@hpcc-js/common";
3
+ import { extent as d3Extent } from "d3-array";
4
+ import { scaleLinear as d3ScaleLinear, scaleLog as d3ScaleLog, scalePow as d3ScalePow, scaleSqrt as d3ScaleSqrt } from "d3-scale";
5
+ import { select as d3Select } from "d3-selection";
6
+ import {
7
+ area as d3Area,
8
+ curveBasis as d3CurveBasis, curveBundle as d3CurveBundle, curveCardinal as d3CurveCardinal, curveCatmullRom as d3curveCatmullRom, curveLinear as d3CurveLinear,
9
+ curveMonotoneX as d3CurveMonotoneX, curveNatural as d3CurveNatural, curveStep as d3CurveStep, curveStepAfter as d3CurveStepAfter, curveStepBefore as d3CurveStepBefore,
10
+ line as d3Line
11
+ } from "d3-shape";
12
+ import { XYAxis } from "./XYAxis.ts";
13
+
14
+ import "../src/Scatter.css";
15
+
16
+ export class Scatter extends XYAxis {
17
+ static __inputs: InputField[] = [{
18
+ id: "label",
19
+ type: "any"
20
+ }, {
21
+ id: "values",
22
+ type: "number",
23
+ multi: true
24
+ }];
25
+
26
+ constructor() {
27
+ super();
28
+ INDChart.call(this);
29
+ ITooltip.call(this);
30
+ this
31
+ .xAxisGuideLines_default(true)
32
+ .yAxisGuideLines_default(true)
33
+ ;
34
+ }
35
+
36
+ xPos(host: XYAxis, d) {
37
+ return host.orientation() === "horizontal" ? host.dataPos(d.label) : host.valuePos(d.value);
38
+ }
39
+
40
+ yPos(host: XYAxis, d) {
41
+ return host.orientation() === "horizontal" ? host.valuePos(d.value) : host.dataPos(d.label);
42
+ }
43
+
44
+ private curve(): any {
45
+ switch (this.interpolate()) {
46
+ case "linear":
47
+ return d3CurveLinear;
48
+ case "step":
49
+ return d3CurveStep;
50
+ case "step-before":
51
+ return d3CurveStepBefore;
52
+ case "step-after":
53
+ return d3CurveStepAfter;
54
+ case "basis":
55
+ return d3CurveBasis;
56
+ case "bundle":
57
+ return d3CurveBundle;
58
+ case "cardinal":
59
+ return d3CurveCardinal;
60
+ case "catmullRom":
61
+ return d3curveCatmullRom;
62
+ case "natural":
63
+ return d3CurveNatural;
64
+ case "monotone":
65
+ default:
66
+ return d3CurveMonotoneX;
67
+ }
68
+ }
69
+
70
+ private getScale() {
71
+ switch (this.pointSizeScale()) {
72
+ case "linear":
73
+ return d3ScaleLinear();
74
+ case "pow":
75
+ return d3ScalePow().exponent(2);
76
+ case "log":
77
+ return d3ScaleLog();
78
+ case "sqrt":
79
+ return d3ScaleSqrt();
80
+ }
81
+ }
82
+
83
+ protected pointColor(row, col, value, origRow) {
84
+ if (this.interpolate() && this.pointDarken()) {
85
+ return this.strokeColor(row, col, value, origRow);
86
+ }
87
+ return this.fillColor(row, col, value, origRow);
88
+ }
89
+
90
+ protected lineColor(row, col, value, origRow) {
91
+ if (this.interpolateFill() && this.interpolateDarken()) {
92
+ return this.strokeColor(row, col, value, origRow);
93
+ }
94
+ return this.fillColor(row, col, value, origRow);
95
+ }
96
+
97
+ protected areaColor(row, col, value, origRow) {
98
+ return this.fillColor(row, col, value, origRow);
99
+ }
100
+
101
+ layerEnter(host: XYAxis, element, duration: number = 250) {
102
+ super.layerEnter(host, element, duration);
103
+ const context = this;
104
+ this
105
+ .tooltipHTML(function (d) {
106
+ switch (context.tooltipStyle()) {
107
+ case "series-table":
108
+ return context.tooltipFormat({
109
+ label: d.label,
110
+ arr: context.columns().slice(1).map(function (column, i) {
111
+ return {
112
+ label: column,
113
+ color: context._palette(column),
114
+ value: context.data()[d.rowIdx][i + 1]
115
+ };
116
+ })
117
+ });
118
+ default:
119
+ return context.tooltipFormat({ label: d.label, series: d.column, value: d.value });
120
+ }
121
+ })
122
+ ;
123
+ }
124
+
125
+ protected _prevPointShape;
126
+ layerUpdate(host: XYAxis, element, duration: number = 250) {
127
+ super.layerUpdate(host, element);
128
+ const isHorizontal = host.orientation() === "horizontal";
129
+ const height = isHorizontal ? this.height() : this.width();
130
+ const context = this;
131
+
132
+ if (this.tabNavigation() && host.parentRelativeDiv) {
133
+ host.parentRelativeDiv
134
+ .attr("tabindex", "0")
135
+ .attr("role", "group")
136
+ .attr("aria-label", `${this.columns()[0] || "Chart"} data`);
137
+ } else if (host.parentRelativeDiv) {
138
+ host.parentRelativeDiv
139
+ .attr("tabindex", null)
140
+ .attr("role", null)
141
+ .attr("aria-label", null);
142
+ }
143
+
144
+ this._palette = this._palette.switch(this.paletteID());
145
+ if (this.useClonedPalette()) {
146
+ this._palette = this._palette.cloneNotExists(this.paletteID() + "_" + this.id());
147
+ }
148
+
149
+ if (this._prevPointShape !== this.pointShape()) {
150
+ element.selectAll(".data").remove();
151
+ this._prevPointShape = this.pointShape();
152
+ }
153
+
154
+ function mapShape(shape) {
155
+ switch (shape) {
156
+ case "rectangle":
157
+ return "rect";
158
+ case "circle":
159
+ return "circle";
160
+ case "cross":
161
+ return "path";
162
+ default:
163
+ }
164
+ }
165
+ const usePointSizeColumn = this.pointSizeColumn_exists();
166
+ let pointSizeColumnIdx;
167
+ let extent;
168
+ let scale;
169
+ if (usePointSizeColumn) {
170
+ pointSizeColumnIdx = this.columns().indexOf(this.pointSizeColumn());
171
+ extent = d3Extent(this.data(), d => d[pointSizeColumnIdx]);
172
+ scale = this.getScale().domain(extent);
173
+ }
174
+ const layerColumns = this.layerColumns(host);
175
+ const layerData = this.layerData(host);
176
+ const flatData = this.flattenData(layerColumns, layerData).map(function (d) {
177
+ d.shape = mapShape(context.pointShape());
178
+ d.column = layerColumns[d.colIdx];
179
+ d.row = layerData[d.rowIdx];
180
+ d.origRow = (layerData[d.rowIdx] as any).__hpcc_origRow;
181
+ if (extent) {
182
+ d.size = scale(d.row[pointSizeColumnIdx]) * (context.maxPointSize() - context.minPointSize()) + context.minPointSize();
183
+ return d.column === context.pointSizeColumn() ? false : d;
184
+ } else {
185
+ d.size = context.pointSize();
186
+ return d;
187
+ }
188
+
189
+ }).filter(d => d);
190
+
191
+ const areas = element.selectAll(".area").data(layerColumns.filter(function (_d, idx) { return context.interpolate() && context.interpolateFill() && idx > 0; }));
192
+ const areasEnter = areas.enter().append("path");
193
+ const area = d3Area()
194
+ .curve(this.curve())
195
+ ;
196
+ if (isHorizontal) {
197
+ area
198
+ .x(function (d) { return context.xPos(host, d); })
199
+ .y0(Math.min(height, this.yPos(host, { value: 0 })))
200
+ .y1(function (d) { return context.yPos(host, d); })
201
+ ;
202
+ } else {
203
+ area
204
+ .y(function (d) { return context.yPos(host, d); })
205
+ .x0(Math.max(0, this.xPos(host, { value: 0 })))
206
+ .x1(function (d) { return context.xPos(host, d); })
207
+ ;
208
+ }
209
+ areasEnter.merge(areas)
210
+ .attr("class", d => "area series series-" + this.cssTag(d))
211
+ .each(function (_d, idx) {
212
+ const element = d3Select(this);
213
+ element
214
+ .attr("d", area(flatData.filter(function (d2) { return d2.colIdx === idx + 1; })))
215
+ .style("opacity", context.interpolateFillOpacity())
216
+ .style("stroke", "none")
217
+ .style("fill", context.areaColor([], _d, undefined, []))
218
+ ;
219
+ });
220
+ areas.exit().remove();
221
+
222
+ const lines = element.selectAll(".line").data(layerColumns.filter(function (_d, idx) { return context.interpolate() && idx > 0; }));
223
+ const linesEnter = lines.enter().append("path");
224
+ const line = d3Line()
225
+ .x(function (d) { return context.xPos(host, d); })
226
+ .y(function (d) { return context.yPos(host, d); })
227
+ .curve(this.curve())
228
+ ;
229
+ linesEnter.merge(lines)
230
+ .attr("class", d => "line series series-" + this.cssTag(d))
231
+ .each(function (_d, idx) {
232
+ const element = d3Select(this);
233
+ const data2 = flatData.filter(function (d2) { return d2.colIdx === idx + 1; });
234
+ element
235
+ .attr("d", line(data2))
236
+ .style("stroke", context.lineColor([], _d, undefined, []))
237
+ .style("fill", "none")
238
+ ;
239
+ });
240
+ lines.exit().remove();
241
+
242
+ const points = element.selectAll(".point").data(flatData, function (d, idx) { return d.shape + "_" + idx; });
243
+ points.enter().append("g")
244
+ .each(function (this: SVGElement, d2) {
245
+ const element = d3Select(this);
246
+ element
247
+ .append(d2.shape)
248
+ .attr("class", "pointShape")
249
+ ;
250
+ element
251
+ .append("text")
252
+ .attr("class", "pointValue")
253
+ .style("display", "none")
254
+ .attr("text-anchor", context.valueAnchor())
255
+ .attr("alignment-baseline", context.valueBaseline())
256
+ .attr("fill", function (d: any, _idx) {
257
+ const useTextColor = context.valueBaseline() === "middle" || context.valueBaseline() === "central";
258
+ return useTextColor ? context.textColor(d.row, d.column, d.value, d.origRow) : null;
259
+ })
260
+ ;
261
+ element
262
+ .append("circle")
263
+ .attr("class", "pointSelection")
264
+ .on("mouseout.tooltip", context.tooltip.hide)
265
+ .on("mousemove.tooltip", context.tooltip.show)
266
+ .call(host._selection.enter.bind(host._selection))
267
+ .on("click", function (d: any, _idx) {
268
+ context.click(host.rowToObj(host.data()[d.rowIdx]), d.column, host._selection.selected(this));
269
+ })
270
+ .on("dblclick", function (d: any, _idx) {
271
+ context.dblclick(host.rowToObj(host.data()[d.rowIdx]), d.column, host._selection.selected(this));
272
+ })
273
+ .on("keydown", function (evt, d: any) {
274
+ if (context.tabNavigation()) {
275
+ const event = d3Event();
276
+ if (event.code === "Space" || event.key === "Enter") {
277
+ event.preventDefault();
278
+ host._selection.click(this);
279
+ }
280
+ }
281
+ })
282
+ ;
283
+ })
284
+ .merge(points)
285
+ .attr("class", d => "point series series-" + this.cssTag(d.column))
286
+ .each(function (this: SVGElement, d2) {
287
+ const textSelection = d3Select(this).select(".pointValue");
288
+ textSelection
289
+ .attr("x", function (d) { return context.xPos(host, d); })
290
+ .attr("y", function (d) { return context.yPos(host, d); })
291
+ .style("display", context.showValue() ? "block" : "none")
292
+ .attr("text-anchor", context.valueAnchor())
293
+ .attr("alignment-baseline", context.valueBaseline())
294
+ .text(function (d) {
295
+ return d["value"];
296
+ })
297
+ ;
298
+ const elementSelection = d3Select(this).select(".pointSelection");
299
+ elementSelection
300
+ .attr("cx", function (d) { return context.xPos(host, d); })
301
+ .attr("cy", function (d) { return context.yPos(host, d); })
302
+ .attr("r", d2.size)
303
+ .attr("tabindex", context.tabNavigation() ? 0 : null)
304
+ .attr("role", context.tabNavigation() ? "button" : null)
305
+ .attr("aria-label", context.tabNavigation() ? (d: any) => `${d.column || "Value"}: ${d.value} @ ${d.label}` : null)
306
+ ;
307
+
308
+ const element = d3Select(this).select(".pointShape");
309
+ switch (d2.shape) {
310
+ case "rect":
311
+ element
312
+ .attr("x", function (d) { return context.xPos(host, d) - d2.size / 2; })
313
+ .attr("y", function (d) { return context.yPos(host, d) - d2.size / 2; })
314
+ .attr("width", d2.size)
315
+ .attr("height", d2.size)
316
+ .style("fill", context.pointColor(d2.row, d2.column, d2.value, d2.origRow))
317
+ ;
318
+ break;
319
+ case "circle":
320
+ element
321
+ .attr("cx", function (d) { return context.xPos(host, d); })
322
+ .attr("cy", function (d) { return context.yPos(host, d); })
323
+ .attr("r", d2.size * 0.9)
324
+ .style("fill", context.pointColor(d2.row, d2.column, d2.value, d2.origRow))
325
+ ;
326
+ break;
327
+ case "path":
328
+ element
329
+ .attr("d", function (d: any) {
330
+ return "M" + (context.xPos(host, d) - d2.size / 2) + " " + (context.yPos(host, d) - d2.size / 2) + " " +
331
+ "L" + (context.xPos(host, d) + d2.size / 2) + " " + (context.yPos(host, d) + d2.size / 2) + " " +
332
+ "M" + (context.xPos(host, d) - d2.size / 2) + " " + (context.yPos(host, d) + d2.size / 2) + " " +
333
+ "L" + (context.xPos(host, d) + d2.size / 2) + " " + (context.yPos(host, d) - d2.size / 2);
334
+ })
335
+ .style("stroke", context.pointColor(d2.row, d2.column, d2.value, d2.origRow))
336
+ ;
337
+ break;
338
+ default:
339
+ }
340
+ })
341
+ ;
342
+ points.exit().remove();
343
+ }
344
+
345
+ exit(domNode, element) {
346
+ super.exit(domNode, element);
347
+ }
348
+ }
349
+ Scatter.prototype._class += " chart_Scatter";
350
+ Scatter.prototype.implements(INDChart.prototype);
351
+ Scatter.prototype.implements(ITooltip.prototype);
352
+
353
+ export interface Scatter {
354
+
355
+ valueAnchor(): string;
356
+ valueAnchor(_: string): this;
357
+ valueBaseline(): string;
358
+ valueBaseline(_: string): this;
359
+ showValue(): boolean;
360
+ showValue(_: boolean): this;
361
+ pointDarken(): boolean;
362
+ pointDarken(_: boolean): this;
363
+ interpolateDarken(): boolean;
364
+ interpolateDarken(_: boolean): this;
365
+
366
+ paletteID(): string;
367
+ paletteID(_: string): this;
368
+ useClonedPalette(): boolean;
369
+ useClonedPalette(_: boolean): this;
370
+ pointSizeScale(): string;
371
+ pointSizeScale(_: string): this;
372
+ pointShape(): string;
373
+ pointShape(_: string): this;
374
+ pointSize(): number;
375
+ pointSize(_: number): this;
376
+ interpolate(): string;
377
+ interpolate(_: string): this;
378
+ interpolate_default(): string;
379
+ interpolate_default(_: string): this;
380
+ interpolateFill(): boolean;
381
+ interpolateFill(_: boolean): this;
382
+ interpolateFill_default(): boolean;
383
+ interpolateFill_default(_: boolean): this;
384
+ interpolateFillOpacity(): number;
385
+ interpolateFillOpacity(_: number): this;
386
+
387
+ // INDChart
388
+ fillColor(row, column, value, origRow): string;
389
+ strokeColor(row, column, value, origRow): string;
390
+ textColor(row, column, value, origRow): string;
391
+ dblclick(row, column, selected): void;
392
+
393
+ // ITooltip
394
+ tooltip;
395
+ tooltipHTML(_): string;
396
+ tooltipFormat(_): string;
397
+ tooltipStyle(): "default" | "none" | "series-table";
398
+ tooltipStyle(_: "default" | "none" | "series-table"): this;
399
+ }
400
+ Scatter.prototype.publish("paletteID", "default", "set", "Color palette for this widget", Scatter.prototype._palette.switch(), { tags: ["Basic", "Shared"] });
401
+ Scatter.prototype.publish("pointSizeScale", "linear", "set", "pointSizeScale", ["linear", "pow", "log", "sqrt"]);
402
+ Scatter.prototype.publish("pointShape", "cross", "set", "Shape of the data points", ["circle", "rectangle", "cross"]);
403
+ Scatter.prototype.publish("pointSize", 6, "number", "Point Size", null, { range: { min: 1, step: 1, max: 200 } });
404
+ Scatter.prototype.publish("interpolate", "", "set", "Interpolate Data", ["", "linear", "step", "step-before", "step-after", "basis", "bundle", "cardinal", "catmullRom", "natural", "monotone"]);
405
+ Scatter.prototype.publish("pointDarken", true, "boolean", "If true, and interpolate is set, then points will have a slightly darker color than their assigned palette color", null, { disable: w => !w.interpolate() });
406
+ Scatter.prototype.publish("interpolateDarken", true, "boolean", "If true, and interpolateFill is true, then lines will have a slightly darker color than their assigned palette color", null, { disable: w => !w.interpolateFill() });
407
+ Scatter.prototype.publish("interpolateFill", false, "boolean", "If true, the area between the line and zero will be filled");
408
+ Scatter.prototype.publish("interpolateFillOpacity", 0.66, "number", "Fill interpolation Opacity", null, { range: { min: 0, step: 0.01, max: 1 } });
409
+ Scatter.prototype.publish("useClonedPalette", false, "boolean", "Enable or disable using a cloned palette", null, { tags: ["Intermediate", "Shared"] });
410
+ Scatter.prototype.publish("showValue", false, "boolean");
411
+ Scatter.prototype.publish("valueAnchor", "middle", "set", "text-anchor for shown value text", ["start", "middle", "end"]);
412
+ Scatter.prototype.publish("valueBaseline", "ideographic", "set", "alignment-baseline for shown value text", ["auto", "baseline", "before-edge", "text-before-edge", "middle", "central", "after-edge", "text-after-edge", "ideographic", "alphabetic", "hanging", "mathematical", "inherit"]);