cx 25.2.0 → 25.3.1

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 (113) hide show
  1. package/dist/manifest.js +606 -606
  2. package/dist/widgets.js +15 -4
  3. package/package.json +32 -32
  4. package/src/charts/Legend.js +167 -167
  5. package/src/charts/Legend.scss +40 -40
  6. package/src/charts/LegendEntry.js +128 -128
  7. package/src/charts/LegendEntry.scss +27 -27
  8. package/src/charts/PieChart.d.ts +92 -92
  9. package/src/charts/PieChart.js +529 -529
  10. package/src/charts/axis/Axis.d.ts +113 -113
  11. package/src/charts/axis/Axis.js +280 -280
  12. package/src/charts/axis/CategoryAxis.d.ts +30 -30
  13. package/src/charts/axis/CategoryAxis.js +241 -241
  14. package/src/charts/axis/NumericAxis.js +351 -351
  15. package/src/charts/axis/Stack.js +55 -55
  16. package/src/charts/axis/TimeAxis.d.ts +28 -28
  17. package/src/charts/axis/TimeAxis.js +611 -611
  18. package/src/charts/helpers/PointReducer.js +47 -47
  19. package/src/charts/helpers/SnapPointFinder.js +69 -69
  20. package/src/core.d.ts +40 -1
  21. package/src/data/Binding.spec.js +69 -69
  22. package/src/data/Expression.js +229 -229
  23. package/src/data/Expression.spec.js +229 -229
  24. package/src/data/StringTemplate.js +92 -92
  25. package/src/data/StringTemplate.spec.js +132 -132
  26. package/src/data/StructuredSelector.js +132 -132
  27. package/src/data/View.d.ts +36 -12
  28. package/src/data/getAccessor.spec.js +11 -11
  29. package/src/data/getSelector.js +49 -49
  30. package/src/hooks/createLocalStorageRef.d.ts +3 -3
  31. package/src/hooks/createLocalStorageRef.js +20 -20
  32. package/src/index.scss +6 -6
  33. package/src/ui/Culture.d.ts +57 -57
  34. package/src/ui/Culture.js +139 -139
  35. package/src/ui/FocusManager.js +171 -171
  36. package/src/ui/Format.js +108 -108
  37. package/src/ui/HoverSync.js +147 -147
  38. package/src/ui/Instance.d.ts +72 -72
  39. package/src/ui/Instance.js +614 -614
  40. package/src/ui/Repeater.d.ts +61 -61
  41. package/src/ui/ResizeManager.d.ts +4 -3
  42. package/src/ui/index.d.ts +42 -42
  43. package/src/ui/layout/ContentPlaceholder.d.ts +19 -19
  44. package/src/ui/layout/ContentPlaceholder.js +105 -105
  45. package/src/ui/layout/ContentPlaceholder.spec.js +579 -579
  46. package/src/ui/layout/LabelsTopLayout.js +134 -134
  47. package/src/util/date/encodeDate.d.ts +1 -1
  48. package/src/util/date/encodeDate.js +8 -8
  49. package/src/util/date/encodeDateWithTimezoneOffset.d.ts +1 -1
  50. package/src/util/date/index.d.ts +11 -11
  51. package/src/util/date/index.js +11 -11
  52. package/src/util/date/parseDateInvariant.d.ts +3 -3
  53. package/src/util/date/parseDateInvariant.js +20 -20
  54. package/src/util/debounce.d.ts +3 -4
  55. package/src/util/getSearchQueryPredicate.js +59 -59
  56. package/src/util/index.d.ts +51 -51
  57. package/src/util/index.js +54 -54
  58. package/src/util/isValidIdentifierName.d.ts +1 -1
  59. package/src/util/isValidIdentifierName.js +5 -5
  60. package/src/util/isValidIdentifierName.spec.js +33 -33
  61. package/src/util/scss/add-rules.scss +38 -38
  62. package/src/widgets/CxCredit.scss +37 -37
  63. package/src/widgets/HighlightedSearchText.js +36 -36
  64. package/src/widgets/HighlightedSearchText.scss +18 -18
  65. package/src/widgets/HtmlElement.d.ts +4 -0
  66. package/src/widgets/List.scss +91 -91
  67. package/src/widgets/drag-drop/DropZone.js +214 -214
  68. package/src/widgets/form/Calendar.js +618 -618
  69. package/src/widgets/form/Calendar.scss +196 -196
  70. package/src/widgets/form/Checkbox.scss +127 -127
  71. package/src/widgets/form/ColorField.js +397 -397
  72. package/src/widgets/form/ColorField.scss +96 -96
  73. package/src/widgets/form/ColorPicker.js +485 -480
  74. package/src/widgets/form/ColorPicker.scss +283 -283
  75. package/src/widgets/form/DateTimeField.js +576 -576
  76. package/src/widgets/form/DateTimePicker.js +392 -392
  77. package/src/widgets/form/LookupField.d.ts +179 -179
  78. package/src/widgets/form/LookupField.scss +219 -219
  79. package/src/widgets/form/MonthField.d.ts +99 -99
  80. package/src/widgets/form/MonthField.js +523 -523
  81. package/src/widgets/form/MonthPicker.d.ts +76 -76
  82. package/src/widgets/form/MonthPicker.js +641 -641
  83. package/src/widgets/form/MonthPicker.scss +118 -118
  84. package/src/widgets/form/NumberField.js +459 -459
  85. package/src/widgets/form/NumberField.scss +61 -61
  86. package/src/widgets/form/Radio.scss +121 -121
  87. package/src/widgets/form/Select.scss +99 -99
  88. package/src/widgets/form/Slider.scss +118 -118
  89. package/src/widgets/form/Switch.scss +140 -140
  90. package/src/widgets/form/TextArea.scss +43 -43
  91. package/src/widgets/form/TextField.js +290 -290
  92. package/src/widgets/form/TextField.scss +55 -55
  93. package/src/widgets/form/UploadButton.d.ts +34 -34
  94. package/src/widgets/form/variables.scss +353 -353
  95. package/src/widgets/grid/Grid.d.ts +442 -442
  96. package/src/widgets/grid/Grid.js +3414 -3414
  97. package/src/widgets/grid/GridRow.js +228 -228
  98. package/src/widgets/grid/TreeNode.d.ts +23 -23
  99. package/src/widgets/grid/TreeNode.scss +88 -88
  100. package/src/widgets/grid/variables.scss +133 -133
  101. package/src/widgets/nav/LinkButton.js +3 -3
  102. package/src/widgets/nav/Menu.scss +74 -74
  103. package/src/widgets/overlay/Dropdown.js +612 -612
  104. package/src/widgets/overlay/FlyweightTooltipTracker.js +39 -39
  105. package/src/widgets/overlay/Overlay.d.ts +73 -73
  106. package/src/widgets/overlay/Tooltip.js +308 -303
  107. package/src/widgets/overlay/Window.js +202 -202
  108. package/src/widgets/overlay/captureMouse.js +124 -124
  109. package/src/widgets/overlay/createHotPromiseWindowFactory.d.ts +18 -18
  110. package/src/widgets/overlay/createHotPromiseWindowFactory.js +56 -56
  111. package/src/widgets/overlay/index.d.ts +11 -11
  112. package/src/widgets/overlay/index.js +11 -11
  113. package/src/widgets/variables.scss +144 -144
@@ -1,529 +1,529 @@
1
- import { Widget, VDOM } from "../ui/Widget";
2
- import { Container } from "../ui/Container";
3
- import { BoundedObject } from "../svg/BoundedObject";
4
- import { Rect } from "../svg/util/Rect";
5
- import { Selection } from "../ui/selection/Selection";
6
- import { tooltipMouseMove, tooltipMouseLeave } from "../widgets/overlay/tooltip-ops";
7
- import { isNumber } from "../util/isNumber";
8
- import { shallowEquals } from "../util/shallowEquals";
9
- import { withHoverSync } from "../ui/HoverSync";
10
-
11
- export class PieChart extends BoundedObject {
12
- declareData() {
13
- super.declareData(...arguments, {
14
- angle: undefined,
15
- startAngle: undefined,
16
- clockwise: undefined,
17
- gap: undefined,
18
- });
19
- }
20
-
21
- explore(context, instance) {
22
- if (!instance.pie) instance.pie = new PieCalculator();
23
- let { data } = instance;
24
- instance.pie.reset(data.angle, data.startAngle, data.clockwise, data.gap);
25
-
26
- context.push("pie", instance.pie);
27
- super.explore(context, instance);
28
- }
29
-
30
- exploreCleanup(context, instance) {
31
- context.pop("pie");
32
- }
33
-
34
- prepare(context, instance) {
35
- this.prepareBounds(context, instance);
36
- let { data, pie } = instance;
37
- pie.measure(data.bounds);
38
- let hash = pie.hash();
39
- instance.cache("hash", hash);
40
- pie.shouldUpdate = !shallowEquals(hash, instance.cached.hash);
41
- if (!pie.shouldUpdate) instance.markShouldUpdate(context);
42
- super.prepare(context, instance);
43
- }
44
- }
45
-
46
- PieChart.prototype.anchors = "0 1 1 0";
47
-
48
- class PieCalculator {
49
- reset(angle, startAngle, clockwise, gap) {
50
- if (angle == 360) angle = 359.99; // really hacky way to draw full circles
51
- this.angleTotal = (angle / 180) * Math.PI;
52
- this.startAngle = (startAngle / 180) * Math.PI;
53
- this.clockwise = clockwise;
54
- this.gap = gap;
55
- this.stacks = {};
56
- }
57
-
58
- acknowledge(stack, value, r, r0, percentageRadius) {
59
- let s = this.stacks[stack];
60
- if (!s) s = this.stacks[stack] = { total: 0, r0s: this.gap > 0 ? [] : null, r0ps: this.gap > 0 ? [] : null };
61
- if (value > 0) {
62
- s.total += value;
63
- if (this.gap > 0 && r0 > 0)
64
- if (percentageRadius) s.r0ps.push(r0);
65
- else s.r0s.push(r0);
66
- }
67
- }
68
-
69
- hash() {
70
- return {
71
- angleTotal: this.angleTotal,
72
- startAngle: this.startAngle,
73
- clockwise: this.clockwise,
74
- stacks: Object.keys(this.stacks)
75
- .map((s) => `${this.stacks[s].angleFactor}`)
76
- .join(":"),
77
- cx: this.cx,
78
- cy: this.cy,
79
- R: this.R,
80
- gap: this.gap,
81
- };
82
- }
83
-
84
- measure(rect) {
85
- this.R = Math.max(0, Math.min(rect.width(), rect.height())) / 2;
86
- for (let s in this.stacks) {
87
- let stack = this.stacks[s];
88
- let gapAngleTotal = 0;
89
- stack.gap = this.gap;
90
- if (this.gap > 0) {
91
- // gap cannot be larger of two times the smallest r0
92
- for (let index = 0; index < stack.r0s.length; index++)
93
- if (2 * stack.r0s[index] < stack.gap) stack.gap = 2 * stack.r0s[index];
94
- for (let index = 0; index < stack.r0ps.length; index++) {
95
- let r0 = (stack.r0ps[index] * this.R) / 100;
96
- if (2 * r0 < stack.gap) stack.gap = 2 * r0;
97
- }
98
- }
99
- while (stack.gap > 0) {
100
- for (let index = 0; index < stack.r0s.length; index++)
101
- gapAngleTotal += 2 * Math.asin(stack.gap / stack.r0s[index] / 2);
102
-
103
- for (let index = 0; index < stack.r0ps.length; index++)
104
- gapAngleTotal += 2 * Math.asin(stack.gap / ((stack.r0ps[index] * this.R) / 100) / 2);
105
-
106
- if (gapAngleTotal < 0.25 * this.angleTotal) break;
107
- stack.gap = stack.gap * 0.95;
108
- gapAngleTotal = 0;
109
- }
110
- if (gapAngleTotal == 0) stack.gap = 0;
111
- stack.angleFactor = stack.total > 0 ? (this.angleTotal - gapAngleTotal) / stack.total : 0;
112
- stack.lastAngle = this.startAngle;
113
- }
114
- this.cx = (rect.l + rect.r) / 2;
115
- this.cy = (rect.t + rect.b) / 2;
116
- }
117
-
118
- map(stack, value, r, r0, percentageRadius) {
119
- if (percentageRadius) {
120
- r = (r * this.R) / 100;
121
- r0 = (r0 * this.R) / 100;
122
- }
123
- let s = this.stacks[stack];
124
- let angle = value * s.angleFactor;
125
- let startAngle = s.lastAngle;
126
- let clockFactor = this.clockwise ? -1 : 1;
127
- let gapAngle = r0 > 0 && s.gap > 0 ? 2 * Math.asin(s.gap / r0 / 2) : 0;
128
- s.lastAngle += clockFactor * (angle + gapAngle);
129
- let endAngle = startAngle + clockFactor * (angle + gapAngle);
130
-
131
- return {
132
- startAngle,
133
- endAngle: startAngle + clockFactor * (angle + gapAngle),
134
- angle,
135
- midAngle: (startAngle + endAngle) / 2,
136
- gap: s.gap,
137
- cx: this.cx,
138
- cy: this.cy,
139
- R: this.R,
140
- };
141
- }
142
- }
143
-
144
- function createSvgArc(cx, cy, r0 = 0, r, startAngle, endAngle, br = 0, gap = 0) {
145
- let gap2 = gap / 2;
146
-
147
- if (startAngle > endAngle) {
148
- let s = startAngle;
149
- startAngle = endAngle;
150
- endAngle = s;
151
- }
152
-
153
- let path = [];
154
- // limit br size based on r and r0
155
- if (br > (r - r0) / 2) br = (r - r0) / 2;
156
-
157
- if (br > 0) {
158
- if (r0 > 0) {
159
- let innerBr = br;
160
- let innerSmallArcAngle = Math.asin((br + gap2) / (r0 + br));
161
-
162
- // adjust br according to the available area
163
- if (innerSmallArcAngle > (endAngle - startAngle) / 2) {
164
- innerSmallArcAngle = (endAngle - startAngle) / 2;
165
- let sin = Math.sin(innerSmallArcAngle);
166
- innerBr = Math.max((r0 * sin - gap2) / (1 - sin), 0);
167
- }
168
-
169
- let innerHipDiagonal = (r0 + innerBr) * Math.cos(innerSmallArcAngle);
170
-
171
- let innerSmallArc1XFrom = cx + Math.cos(endAngle) * innerHipDiagonal + Math.cos(endAngle - Math.PI / 2) * gap2;
172
- let innerSmallArc1YFrom = cy - Math.sin(endAngle) * innerHipDiagonal - Math.sin(endAngle - Math.PI / 2) * gap2;
173
-
174
- // move from the first small inner arc
175
- path.push(move(innerSmallArc1XFrom, innerSmallArc1YFrom));
176
-
177
- let innerSmallArc1XTo = cx + Math.cos(endAngle - innerSmallArcAngle) * r0;
178
- let innerSmallArc1YTo = cy - Math.sin(endAngle - innerSmallArcAngle) * r0;
179
-
180
- // add first small inner arc
181
- path.push(arc(innerBr, innerBr, 0, 0, 0, innerSmallArc1XTo, innerSmallArc1YTo));
182
-
183
- // SECOND ARC
184
-
185
- let innerArcXTo = cx + Math.cos(startAngle + innerSmallArcAngle) * r0;
186
- let innerArcYTo = cy - Math.sin(startAngle + innerSmallArcAngle) * r0;
187
- // add large inner arc
188
- path.push(
189
- arc(
190
- r0,
191
- r0,
192
- 0,
193
- largeArcFlag(endAngle - innerSmallArcAngle - startAngle - innerSmallArcAngle),
194
- 1,
195
- innerArcXTo,
196
- innerArcYTo,
197
- ),
198
- );
199
-
200
- let innerSmallArc2XTo =
201
- cx + Math.cos(startAngle) * innerHipDiagonal + Math.cos(startAngle + Math.PI / 2) * gap2;
202
- let innerSmallArc2YTo =
203
- cy - Math.sin(startAngle) * innerHipDiagonal - Math.sin(startAngle + Math.PI / 2) * gap2;
204
- // add second small inner arc
205
- path.push(arc(innerBr, innerBr, 0, 0, 0, innerSmallArc2XTo, innerSmallArc2YTo));
206
- } else {
207
- path.push(move(cx, cy));
208
- }
209
-
210
- let outerBr = br;
211
- let outerSmallArcAngle = Math.asin((br + gap2) / (r - br));
212
-
213
- // tweak br according to the available area
214
- if (outerSmallArcAngle > (endAngle - startAngle) / 2) {
215
- outerSmallArcAngle = (endAngle - startAngle) / 2;
216
- let sin = Math.sin(outerSmallArcAngle);
217
- outerBr = Math.max((r * sin - gap2) / (1 + sin), 0);
218
- }
219
-
220
- let outerHipDiagonal = Math.cos(outerSmallArcAngle) * (r - outerBr);
221
-
222
- let outerSmallArc1XFrom =
223
- cx + Math.cos(startAngle) * outerHipDiagonal + Math.cos(startAngle + Math.PI / 2) * gap2;
224
- let outerSmallArc1YFrom =
225
- cy - Math.sin(startAngle) * outerHipDiagonal - Math.sin(startAngle + Math.PI / 2) * gap2;
226
-
227
- let outerSmallArc1XTo = cx + Math.cos(startAngle + outerSmallArcAngle) * r;
228
- let outerSmallArc1YTo = cy - Math.sin(startAngle + outerSmallArcAngle) * r;
229
-
230
- let outerLargeArcXTo = cx + Math.cos(endAngle - outerSmallArcAngle) * r;
231
- let outerLargeArcYTo = cy - Math.sin(endAngle - outerSmallArcAngle) * r;
232
-
233
- let outerSmallArc2XTo = cx + Math.cos(endAngle) * outerHipDiagonal + Math.cos(endAngle - Math.PI / 2) * gap2;
234
- let outerSmallArc2YTo = cy - Math.sin(endAngle) * outerHipDiagonal - Math.sin(endAngle - Math.PI / 2) * gap2;
235
-
236
- path.push(
237
- line(outerSmallArc1XFrom, outerSmallArc1YFrom),
238
- arc(outerBr, outerBr, 0, 0, 0, outerSmallArc1XTo, outerSmallArc1YTo),
239
- arc(
240
- r,
241
- r,
242
- 0,
243
- largeArcFlag(endAngle - outerSmallArcAngle - startAngle - outerSmallArcAngle),
244
- 0,
245
- outerLargeArcXTo,
246
- outerLargeArcYTo,
247
- ),
248
- arc(outerBr, outerBr, 0, 0, 0, outerSmallArc2XTo, outerSmallArc2YTo),
249
- );
250
- } else {
251
- if (r0 > 0) {
252
- let innerGapAngle = r0 > 0 && gap2 > 0 ? Math.asin(gap2 / r0) : 0;
253
- let innerStartAngle = startAngle + innerGapAngle;
254
- let innerEndAngle = endAngle - innerGapAngle;
255
- let startX = cx + Math.cos(innerEndAngle) * r0;
256
- let startY = cy - Math.sin(innerEndAngle) * r0;
257
- path.push(move(startX, startY));
258
-
259
- let innerArcToX = cx + Math.cos(innerStartAngle) * r0;
260
- let innerArcToY = cy - Math.sin(innerStartAngle) * r0;
261
-
262
- path.push(arc(r0, r0, 0, largeArcFlag(innerStartAngle - innerEndAngle), 1, innerArcToX, innerArcToY));
263
- } else {
264
- path.push(move(cx, cy));
265
- }
266
-
267
- let outerGapAngle = r > 0 && gap2 > 0 ? Math.asin(gap2 / r) : 0;
268
- let outerStartAngle = startAngle + outerGapAngle;
269
- let outerEndAngle = endAngle - outerGapAngle;
270
- let lineToX = cx + Math.cos(outerStartAngle) * r;
271
- let lineToY = cy - Math.sin(outerStartAngle) * r;
272
- path.push(line(lineToX, lineToY));
273
-
274
- let arcToX = cx + Math.cos(outerEndAngle) * r;
275
- let arcToY = cy - Math.sin(outerEndAngle) * r;
276
- path.push(arc(r, r, 0, largeArcFlag(outerEndAngle - outerStartAngle), 0, arcToX, arcToY));
277
- }
278
-
279
- path.push(z());
280
- return path.join(" ");
281
- }
282
-
283
- PieChart.prototype.anchors = "0 1 1 0";
284
- PieChart.prototype.angle = 360;
285
- PieChart.prototype.startAngle = 0;
286
- PieChart.prototype.gap = 0;
287
-
288
- Widget.alias("pie-slice");
289
- export class PieSlice extends Container {
290
- init() {
291
- this.selection = Selection.create(this.selection);
292
- if (this.borderRadius) this.br = this.borderRadius;
293
- super.init();
294
- }
295
-
296
- declareData() {
297
- let selection = this.selection.configureWidget(this);
298
- super.declareData(...arguments, selection, {
299
- active: true,
300
- r0: undefined,
301
- r: undefined,
302
- colorIndex: undefined,
303
- colorMap: undefined,
304
- colorName: undefined,
305
- offset: undefined,
306
- value: undefined,
307
- disabled: undefined,
308
- innerPointRadius: undefined,
309
- outerPointRadius: undefined,
310
- name: undefined,
311
- stack: undefined,
312
- legend: undefined,
313
- hoverId: undefined,
314
- br: undefined,
315
- legendDisplayText: undefined,
316
- });
317
- }
318
-
319
- prepareData(context, instance) {
320
- let { data } = instance;
321
-
322
- if (data.name && !data.colorName) data.colorName = data.name;
323
-
324
- super.prepareData(context, instance);
325
- }
326
-
327
- explore(context, instance) {
328
- instance.pie = context.pie;
329
- if (!instance.pie) throw new Error("Pie.Slice must be placed inside a Pie.");
330
-
331
- let { data } = instance;
332
-
333
- instance.valid = isNumber(data.value) && data.value > 0;
334
-
335
- instance.colorMap = data.colorMap && context.getColorMap && context.getColorMap(data.colorMap);
336
- if (instance.colorMap && data.colorName) instance.colorMap.acknowledge(data.colorName);
337
-
338
- instance.hoverSync = context.hoverSync;
339
-
340
- if (instance.valid && data.active) {
341
- instance.pie.acknowledge(data.stack, data.value, data.r, data.r0, this.percentageRadius);
342
- super.explore(context, instance);
343
- }
344
- }
345
-
346
- prepare(context, instance) {
347
- let { data, segment, pie, colorMap } = instance;
348
-
349
- if (colorMap && data.colorName) {
350
- data.colorIndex = colorMap.map(data.colorName);
351
- if (instance.cache("colorIndex", data.colorIndex)) instance.markShouldUpdate(context);
352
- }
353
-
354
- if (instance.valid && data.active) {
355
- let seg = pie.map(data.stack, data.value, data.r, data.r0, this.percentageRadius);
356
-
357
- if (
358
- !segment ||
359
- instance.shouldUpdate ||
360
- seg.startAngle != segment.startAngle ||
361
- seg.endAngle != segment.endAngle ||
362
- pie.shouldUpdate
363
- ) {
364
- if (data.offset > 0) {
365
- seg.ox = seg.cx + Math.cos(seg.midAngle) * data.offset;
366
- seg.oy = seg.cy - Math.sin(seg.midAngle) * data.offset;
367
- } else {
368
- seg.ox = seg.cx;
369
- seg.oy = seg.cy;
370
- }
371
-
372
- seg.radiusMultiplier = 1;
373
- if (this.percentageRadius) seg.radiusMultiplier = seg.R / 100;
374
-
375
- let innerR = data.innerPointRadius != null ? data.innerPointRadius : data.r0;
376
- let outerR = data.outerPointRadius != null ? data.outerPointRadius : data.r;
377
-
378
- let ix = seg.ox + Math.cos(seg.midAngle) * innerR * seg.radiusMultiplier;
379
- let iy = seg.oy - Math.sin(seg.midAngle) * innerR * seg.radiusMultiplier;
380
- let ox = seg.ox + Math.cos(seg.midAngle) * outerR * seg.radiusMultiplier;
381
- let oy = seg.oy - Math.sin(seg.midAngle) * outerR * seg.radiusMultiplier;
382
-
383
- instance.segment = seg;
384
- instance.bounds = new Rect({
385
- l: ix,
386
- r: ox,
387
- t: iy,
388
- b: oy,
389
- });
390
-
391
- instance.markShouldUpdate(context);
392
- }
393
-
394
- context.push("parentRect", instance.bounds);
395
- }
396
-
397
- if (data.name && data.legend && context.addLegendEntry)
398
- context.addLegendEntry(data.legend, {
399
- name: data.name,
400
- active: data.active,
401
- colorIndex: data.colorIndex,
402
- disabled: data.disabled,
403
- selected: this.selection.isInstanceSelected(instance),
404
- style: data.style,
405
- shape: this.legendShape,
406
- hoverId: data.hoverId,
407
- hoverChannel: this.hoverChannel,
408
- hoverSync: instance.hoverSync,
409
- displayText: data.legendDisplayText,
410
- onClick: (e) => {
411
- this.onLegendClick(e, instance);
412
- },
413
- });
414
- }
415
-
416
- prepareCleanup(context, instance) {
417
- if (instance.valid && instance.data.active) {
418
- context.pop("parentRect");
419
- }
420
- }
421
-
422
- onLegendClick(e, instance) {
423
- let allActions = this.legendAction == "auto";
424
- let { data } = instance;
425
- if (allActions || this.legendAction == "toggle") if (instance.set("active", !data.active)) return;
426
-
427
- if (allActions || this.legendAction == "select") this.handleClick(e, instance);
428
- }
429
-
430
- render(context, instance, key) {
431
- let { segment, data } = instance;
432
- if (!instance.valid || !data.active) return null;
433
-
434
- return withHoverSync(
435
- key,
436
- instance.hoverSync,
437
- this.hoverChannel,
438
- data.hoverId,
439
- ({ hover, onMouseMove, onMouseLeave }) => {
440
- let stateMods = {
441
- selected: this.selection.isInstanceSelected(instance),
442
- disabled: data.disabled,
443
- selectable: !this.selection.isDummy,
444
- [`color-${data.colorIndex}`]: data.colorIndex != null,
445
- hover,
446
- };
447
-
448
- let d = createSvgArc(
449
- segment.ox,
450
- segment.oy,
451
- data.r0 * segment.radiusMultiplier,
452
- data.r * segment.radiusMultiplier,
453
- segment.startAngle,
454
- segment.endAngle,
455
- data.br,
456
- segment.gap,
457
- );
458
-
459
- return (
460
- <g key={key} className={data.classNames}>
461
- <path
462
- className={this.CSS.element(this.baseClass, "slice", stateMods)}
463
- style={data.style}
464
- d={d}
465
- onMouseMove={(e) => {
466
- onMouseMove(e, instance);
467
- tooltipMouseMove(e, instance, this.tooltip);
468
- }}
469
- onMouseLeave={(e) => {
470
- onMouseLeave(e, instance);
471
- tooltipMouseLeave(e, instance, this.tooltip);
472
- }}
473
- onClick={(e) => {
474
- this.handleClick(e, instance);
475
- }}
476
- />
477
- {this.renderChildren(context, instance)}
478
- </g>
479
- );
480
- },
481
- );
482
- }
483
-
484
- handleClick(e, instance) {
485
- if (!this.selection.isDummy) {
486
- this.selection.selectInstance(instance, {
487
- toggle: e.ctrlKey,
488
- });
489
- e.stopPropagation();
490
- e.preventDefault();
491
- }
492
- }
493
- }
494
-
495
- function move(x, y) {
496
- return `M ${x} ${y}`;
497
- }
498
-
499
- function line(x, y) {
500
- return `L ${x} ${y}`;
501
- }
502
-
503
- function z() {
504
- return "Z";
505
- }
506
-
507
- function arc(rx, ry, xRotation, largeArc, sweep, x, y) {
508
- return `A ${rx} ${ry} ${xRotation} ${largeArc} ${sweep} ${x} ${y}`;
509
- }
510
-
511
- function largeArcFlag(angle) {
512
- return angle > Math.PI || angle < -Math.PI ? 1 : 0;
513
- }
514
-
515
- PieSlice.prototype.offset = 0;
516
- PieSlice.prototype.r0 = 0;
517
- PieSlice.prototype.r = 50;
518
- PieSlice.prototype.percentageRadius = true;
519
- PieSlice.prototype.baseClass = "pieslice";
520
- PieSlice.prototype.legend = "legend";
521
- PieSlice.prototype.active = true;
522
- PieSlice.prototype.stack = "stack";
523
- PieSlice.prototype.legendAction = "auto";
524
- PieSlice.prototype.legendShape = "circle";
525
- PieSlice.prototype.hoverChannel = "default";
526
- PieSlice.prototype.styled = true;
527
- PieSlice.prototype.br = 0;
528
-
529
- Widget.alias("pie-chart", PieChart);
1
+ import { Widget, VDOM } from "../ui/Widget";
2
+ import { Container } from "../ui/Container";
3
+ import { BoundedObject } from "../svg/BoundedObject";
4
+ import { Rect } from "../svg/util/Rect";
5
+ import { Selection } from "../ui/selection/Selection";
6
+ import { tooltipMouseMove, tooltipMouseLeave } from "../widgets/overlay/tooltip-ops";
7
+ import { isNumber } from "../util/isNumber";
8
+ import { shallowEquals } from "../util/shallowEquals";
9
+ import { withHoverSync } from "../ui/HoverSync";
10
+
11
+ export class PieChart extends BoundedObject {
12
+ declareData() {
13
+ super.declareData(...arguments, {
14
+ angle: undefined,
15
+ startAngle: undefined,
16
+ clockwise: undefined,
17
+ gap: undefined,
18
+ });
19
+ }
20
+
21
+ explore(context, instance) {
22
+ if (!instance.pie) instance.pie = new PieCalculator();
23
+ let { data } = instance;
24
+ instance.pie.reset(data.angle, data.startAngle, data.clockwise, data.gap);
25
+
26
+ context.push("pie", instance.pie);
27
+ super.explore(context, instance);
28
+ }
29
+
30
+ exploreCleanup(context, instance) {
31
+ context.pop("pie");
32
+ }
33
+
34
+ prepare(context, instance) {
35
+ this.prepareBounds(context, instance);
36
+ let { data, pie } = instance;
37
+ pie.measure(data.bounds);
38
+ let hash = pie.hash();
39
+ instance.cache("hash", hash);
40
+ pie.shouldUpdate = !shallowEquals(hash, instance.cached.hash);
41
+ if (!pie.shouldUpdate) instance.markShouldUpdate(context);
42
+ super.prepare(context, instance);
43
+ }
44
+ }
45
+
46
+ PieChart.prototype.anchors = "0 1 1 0";
47
+
48
+ class PieCalculator {
49
+ reset(angle, startAngle, clockwise, gap) {
50
+ if (angle == 360) angle = 359.99; // really hacky way to draw full circles
51
+ this.angleTotal = (angle / 180) * Math.PI;
52
+ this.startAngle = (startAngle / 180) * Math.PI;
53
+ this.clockwise = clockwise;
54
+ this.gap = gap;
55
+ this.stacks = {};
56
+ }
57
+
58
+ acknowledge(stack, value, r, r0, percentageRadius) {
59
+ let s = this.stacks[stack];
60
+ if (!s) s = this.stacks[stack] = { total: 0, r0s: this.gap > 0 ? [] : null, r0ps: this.gap > 0 ? [] : null };
61
+ if (value > 0) {
62
+ s.total += value;
63
+ if (this.gap > 0 && r0 > 0)
64
+ if (percentageRadius) s.r0ps.push(r0);
65
+ else s.r0s.push(r0);
66
+ }
67
+ }
68
+
69
+ hash() {
70
+ return {
71
+ angleTotal: this.angleTotal,
72
+ startAngle: this.startAngle,
73
+ clockwise: this.clockwise,
74
+ stacks: Object.keys(this.stacks)
75
+ .map((s) => `${this.stacks[s].angleFactor}`)
76
+ .join(":"),
77
+ cx: this.cx,
78
+ cy: this.cy,
79
+ R: this.R,
80
+ gap: this.gap,
81
+ };
82
+ }
83
+
84
+ measure(rect) {
85
+ this.R = Math.max(0, Math.min(rect.width(), rect.height())) / 2;
86
+ for (let s in this.stacks) {
87
+ let stack = this.stacks[s];
88
+ let gapAngleTotal = 0;
89
+ stack.gap = this.gap;
90
+ if (this.gap > 0) {
91
+ // gap cannot be larger of two times the smallest r0
92
+ for (let index = 0; index < stack.r0s.length; index++)
93
+ if (2 * stack.r0s[index] < stack.gap) stack.gap = 2 * stack.r0s[index];
94
+ for (let index = 0; index < stack.r0ps.length; index++) {
95
+ let r0 = (stack.r0ps[index] * this.R) / 100;
96
+ if (2 * r0 < stack.gap) stack.gap = 2 * r0;
97
+ }
98
+ }
99
+ while (stack.gap > 0) {
100
+ for (let index = 0; index < stack.r0s.length; index++)
101
+ gapAngleTotal += 2 * Math.asin(stack.gap / stack.r0s[index] / 2);
102
+
103
+ for (let index = 0; index < stack.r0ps.length; index++)
104
+ gapAngleTotal += 2 * Math.asin(stack.gap / ((stack.r0ps[index] * this.R) / 100) / 2);
105
+
106
+ if (gapAngleTotal < 0.25 * this.angleTotal) break;
107
+ stack.gap = stack.gap * 0.95;
108
+ gapAngleTotal = 0;
109
+ }
110
+ if (gapAngleTotal == 0) stack.gap = 0;
111
+ stack.angleFactor = stack.total > 0 ? (this.angleTotal - gapAngleTotal) / stack.total : 0;
112
+ stack.lastAngle = this.startAngle;
113
+ }
114
+ this.cx = (rect.l + rect.r) / 2;
115
+ this.cy = (rect.t + rect.b) / 2;
116
+ }
117
+
118
+ map(stack, value, r, r0, percentageRadius) {
119
+ if (percentageRadius) {
120
+ r = (r * this.R) / 100;
121
+ r0 = (r0 * this.R) / 100;
122
+ }
123
+ let s = this.stacks[stack];
124
+ let angle = value * s.angleFactor;
125
+ let startAngle = s.lastAngle;
126
+ let clockFactor = this.clockwise ? -1 : 1;
127
+ let gapAngle = r0 > 0 && s.gap > 0 ? 2 * Math.asin(s.gap / r0 / 2) : 0;
128
+ s.lastAngle += clockFactor * (angle + gapAngle);
129
+ let endAngle = startAngle + clockFactor * (angle + gapAngle);
130
+
131
+ return {
132
+ startAngle,
133
+ endAngle: startAngle + clockFactor * (angle + gapAngle),
134
+ angle,
135
+ midAngle: (startAngle + endAngle) / 2,
136
+ gap: s.gap,
137
+ cx: this.cx,
138
+ cy: this.cy,
139
+ R: this.R,
140
+ };
141
+ }
142
+ }
143
+
144
+ function createSvgArc(cx, cy, r0 = 0, r, startAngle, endAngle, br = 0, gap = 0) {
145
+ let gap2 = gap / 2;
146
+
147
+ if (startAngle > endAngle) {
148
+ let s = startAngle;
149
+ startAngle = endAngle;
150
+ endAngle = s;
151
+ }
152
+
153
+ let path = [];
154
+ // limit br size based on r and r0
155
+ if (br > (r - r0) / 2) br = (r - r0) / 2;
156
+
157
+ if (br > 0) {
158
+ if (r0 > 0) {
159
+ let innerBr = br;
160
+ let innerSmallArcAngle = Math.asin((br + gap2) / (r0 + br));
161
+
162
+ // adjust br according to the available area
163
+ if (innerSmallArcAngle > (endAngle - startAngle) / 2) {
164
+ innerSmallArcAngle = (endAngle - startAngle) / 2;
165
+ let sin = Math.sin(innerSmallArcAngle);
166
+ innerBr = Math.max((r0 * sin - gap2) / (1 - sin), 0);
167
+ }
168
+
169
+ let innerHipDiagonal = (r0 + innerBr) * Math.cos(innerSmallArcAngle);
170
+
171
+ let innerSmallArc1XFrom = cx + Math.cos(endAngle) * innerHipDiagonal + Math.cos(endAngle - Math.PI / 2) * gap2;
172
+ let innerSmallArc1YFrom = cy - Math.sin(endAngle) * innerHipDiagonal - Math.sin(endAngle - Math.PI / 2) * gap2;
173
+
174
+ // move from the first small inner arc
175
+ path.push(move(innerSmallArc1XFrom, innerSmallArc1YFrom));
176
+
177
+ let innerSmallArc1XTo = cx + Math.cos(endAngle - innerSmallArcAngle) * r0;
178
+ let innerSmallArc1YTo = cy - Math.sin(endAngle - innerSmallArcAngle) * r0;
179
+
180
+ // add first small inner arc
181
+ path.push(arc(innerBr, innerBr, 0, 0, 0, innerSmallArc1XTo, innerSmallArc1YTo));
182
+
183
+ // SECOND ARC
184
+
185
+ let innerArcXTo = cx + Math.cos(startAngle + innerSmallArcAngle) * r0;
186
+ let innerArcYTo = cy - Math.sin(startAngle + innerSmallArcAngle) * r0;
187
+ // add large inner arc
188
+ path.push(
189
+ arc(
190
+ r0,
191
+ r0,
192
+ 0,
193
+ largeArcFlag(endAngle - innerSmallArcAngle - startAngle - innerSmallArcAngle),
194
+ 1,
195
+ innerArcXTo,
196
+ innerArcYTo,
197
+ ),
198
+ );
199
+
200
+ let innerSmallArc2XTo =
201
+ cx + Math.cos(startAngle) * innerHipDiagonal + Math.cos(startAngle + Math.PI / 2) * gap2;
202
+ let innerSmallArc2YTo =
203
+ cy - Math.sin(startAngle) * innerHipDiagonal - Math.sin(startAngle + Math.PI / 2) * gap2;
204
+ // add second small inner arc
205
+ path.push(arc(innerBr, innerBr, 0, 0, 0, innerSmallArc2XTo, innerSmallArc2YTo));
206
+ } else {
207
+ path.push(move(cx, cy));
208
+ }
209
+
210
+ let outerBr = br;
211
+ let outerSmallArcAngle = Math.asin((br + gap2) / (r - br));
212
+
213
+ // tweak br according to the available area
214
+ if (outerSmallArcAngle > (endAngle - startAngle) / 2) {
215
+ outerSmallArcAngle = (endAngle - startAngle) / 2;
216
+ let sin = Math.sin(outerSmallArcAngle);
217
+ outerBr = Math.max((r * sin - gap2) / (1 + sin), 0);
218
+ }
219
+
220
+ let outerHipDiagonal = Math.cos(outerSmallArcAngle) * (r - outerBr);
221
+
222
+ let outerSmallArc1XFrom =
223
+ cx + Math.cos(startAngle) * outerHipDiagonal + Math.cos(startAngle + Math.PI / 2) * gap2;
224
+ let outerSmallArc1YFrom =
225
+ cy - Math.sin(startAngle) * outerHipDiagonal - Math.sin(startAngle + Math.PI / 2) * gap2;
226
+
227
+ let outerSmallArc1XTo = cx + Math.cos(startAngle + outerSmallArcAngle) * r;
228
+ let outerSmallArc1YTo = cy - Math.sin(startAngle + outerSmallArcAngle) * r;
229
+
230
+ let outerLargeArcXTo = cx + Math.cos(endAngle - outerSmallArcAngle) * r;
231
+ let outerLargeArcYTo = cy - Math.sin(endAngle - outerSmallArcAngle) * r;
232
+
233
+ let outerSmallArc2XTo = cx + Math.cos(endAngle) * outerHipDiagonal + Math.cos(endAngle - Math.PI / 2) * gap2;
234
+ let outerSmallArc2YTo = cy - Math.sin(endAngle) * outerHipDiagonal - Math.sin(endAngle - Math.PI / 2) * gap2;
235
+
236
+ path.push(
237
+ line(outerSmallArc1XFrom, outerSmallArc1YFrom),
238
+ arc(outerBr, outerBr, 0, 0, 0, outerSmallArc1XTo, outerSmallArc1YTo),
239
+ arc(
240
+ r,
241
+ r,
242
+ 0,
243
+ largeArcFlag(endAngle - outerSmallArcAngle - startAngle - outerSmallArcAngle),
244
+ 0,
245
+ outerLargeArcXTo,
246
+ outerLargeArcYTo,
247
+ ),
248
+ arc(outerBr, outerBr, 0, 0, 0, outerSmallArc2XTo, outerSmallArc2YTo),
249
+ );
250
+ } else {
251
+ if (r0 > 0) {
252
+ let innerGapAngle = r0 > 0 && gap2 > 0 ? Math.asin(gap2 / r0) : 0;
253
+ let innerStartAngle = startAngle + innerGapAngle;
254
+ let innerEndAngle = endAngle - innerGapAngle;
255
+ let startX = cx + Math.cos(innerEndAngle) * r0;
256
+ let startY = cy - Math.sin(innerEndAngle) * r0;
257
+ path.push(move(startX, startY));
258
+
259
+ let innerArcToX = cx + Math.cos(innerStartAngle) * r0;
260
+ let innerArcToY = cy - Math.sin(innerStartAngle) * r0;
261
+
262
+ path.push(arc(r0, r0, 0, largeArcFlag(innerStartAngle - innerEndAngle), 1, innerArcToX, innerArcToY));
263
+ } else {
264
+ path.push(move(cx, cy));
265
+ }
266
+
267
+ let outerGapAngle = r > 0 && gap2 > 0 ? Math.asin(gap2 / r) : 0;
268
+ let outerStartAngle = startAngle + outerGapAngle;
269
+ let outerEndAngle = endAngle - outerGapAngle;
270
+ let lineToX = cx + Math.cos(outerStartAngle) * r;
271
+ let lineToY = cy - Math.sin(outerStartAngle) * r;
272
+ path.push(line(lineToX, lineToY));
273
+
274
+ let arcToX = cx + Math.cos(outerEndAngle) * r;
275
+ let arcToY = cy - Math.sin(outerEndAngle) * r;
276
+ path.push(arc(r, r, 0, largeArcFlag(outerEndAngle - outerStartAngle), 0, arcToX, arcToY));
277
+ }
278
+
279
+ path.push(z());
280
+ return path.join(" ");
281
+ }
282
+
283
+ PieChart.prototype.anchors = "0 1 1 0";
284
+ PieChart.prototype.angle = 360;
285
+ PieChart.prototype.startAngle = 0;
286
+ PieChart.prototype.gap = 0;
287
+
288
+ Widget.alias("pie-slice");
289
+ export class PieSlice extends Container {
290
+ init() {
291
+ this.selection = Selection.create(this.selection);
292
+ if (this.borderRadius) this.br = this.borderRadius;
293
+ super.init();
294
+ }
295
+
296
+ declareData() {
297
+ let selection = this.selection.configureWidget(this);
298
+ super.declareData(...arguments, selection, {
299
+ active: true,
300
+ r0: undefined,
301
+ r: undefined,
302
+ colorIndex: undefined,
303
+ colorMap: undefined,
304
+ colorName: undefined,
305
+ offset: undefined,
306
+ value: undefined,
307
+ disabled: undefined,
308
+ innerPointRadius: undefined,
309
+ outerPointRadius: undefined,
310
+ name: undefined,
311
+ stack: undefined,
312
+ legend: undefined,
313
+ hoverId: undefined,
314
+ br: undefined,
315
+ legendDisplayText: undefined,
316
+ });
317
+ }
318
+
319
+ prepareData(context, instance) {
320
+ let { data } = instance;
321
+
322
+ if (data.name && !data.colorName) data.colorName = data.name;
323
+
324
+ super.prepareData(context, instance);
325
+ }
326
+
327
+ explore(context, instance) {
328
+ instance.pie = context.pie;
329
+ if (!instance.pie) throw new Error("Pie.Slice must be placed inside a Pie.");
330
+
331
+ let { data } = instance;
332
+
333
+ instance.valid = isNumber(data.value) && data.value > 0;
334
+
335
+ instance.colorMap = data.colorMap && context.getColorMap && context.getColorMap(data.colorMap);
336
+ if (instance.colorMap && data.colorName) instance.colorMap.acknowledge(data.colorName);
337
+
338
+ instance.hoverSync = context.hoverSync;
339
+
340
+ if (instance.valid && data.active) {
341
+ instance.pie.acknowledge(data.stack, data.value, data.r, data.r0, this.percentageRadius);
342
+ super.explore(context, instance);
343
+ }
344
+ }
345
+
346
+ prepare(context, instance) {
347
+ let { data, segment, pie, colorMap } = instance;
348
+
349
+ if (colorMap && data.colorName) {
350
+ data.colorIndex = colorMap.map(data.colorName);
351
+ if (instance.cache("colorIndex", data.colorIndex)) instance.markShouldUpdate(context);
352
+ }
353
+
354
+ if (instance.valid && data.active) {
355
+ let seg = pie.map(data.stack, data.value, data.r, data.r0, this.percentageRadius);
356
+
357
+ if (
358
+ !segment ||
359
+ instance.shouldUpdate ||
360
+ seg.startAngle != segment.startAngle ||
361
+ seg.endAngle != segment.endAngle ||
362
+ pie.shouldUpdate
363
+ ) {
364
+ if (data.offset > 0) {
365
+ seg.ox = seg.cx + Math.cos(seg.midAngle) * data.offset;
366
+ seg.oy = seg.cy - Math.sin(seg.midAngle) * data.offset;
367
+ } else {
368
+ seg.ox = seg.cx;
369
+ seg.oy = seg.cy;
370
+ }
371
+
372
+ seg.radiusMultiplier = 1;
373
+ if (this.percentageRadius) seg.radiusMultiplier = seg.R / 100;
374
+
375
+ let innerR = data.innerPointRadius != null ? data.innerPointRadius : data.r0;
376
+ let outerR = data.outerPointRadius != null ? data.outerPointRadius : data.r;
377
+
378
+ let ix = seg.ox + Math.cos(seg.midAngle) * innerR * seg.radiusMultiplier;
379
+ let iy = seg.oy - Math.sin(seg.midAngle) * innerR * seg.radiusMultiplier;
380
+ let ox = seg.ox + Math.cos(seg.midAngle) * outerR * seg.radiusMultiplier;
381
+ let oy = seg.oy - Math.sin(seg.midAngle) * outerR * seg.radiusMultiplier;
382
+
383
+ instance.segment = seg;
384
+ instance.bounds = new Rect({
385
+ l: ix,
386
+ r: ox,
387
+ t: iy,
388
+ b: oy,
389
+ });
390
+
391
+ instance.markShouldUpdate(context);
392
+ }
393
+
394
+ context.push("parentRect", instance.bounds);
395
+ }
396
+
397
+ if (data.name && data.legend && context.addLegendEntry)
398
+ context.addLegendEntry(data.legend, {
399
+ name: data.name,
400
+ active: data.active,
401
+ colorIndex: data.colorIndex,
402
+ disabled: data.disabled,
403
+ selected: this.selection.isInstanceSelected(instance),
404
+ style: data.style,
405
+ shape: this.legendShape,
406
+ hoverId: data.hoverId,
407
+ hoverChannel: this.hoverChannel,
408
+ hoverSync: instance.hoverSync,
409
+ displayText: data.legendDisplayText,
410
+ onClick: (e) => {
411
+ this.onLegendClick(e, instance);
412
+ },
413
+ });
414
+ }
415
+
416
+ prepareCleanup(context, instance) {
417
+ if (instance.valid && instance.data.active) {
418
+ context.pop("parentRect");
419
+ }
420
+ }
421
+
422
+ onLegendClick(e, instance) {
423
+ let allActions = this.legendAction == "auto";
424
+ let { data } = instance;
425
+ if (allActions || this.legendAction == "toggle") if (instance.set("active", !data.active)) return;
426
+
427
+ if (allActions || this.legendAction == "select") this.handleClick(e, instance);
428
+ }
429
+
430
+ render(context, instance, key) {
431
+ let { segment, data } = instance;
432
+ if (!instance.valid || !data.active) return null;
433
+
434
+ return withHoverSync(
435
+ key,
436
+ instance.hoverSync,
437
+ this.hoverChannel,
438
+ data.hoverId,
439
+ ({ hover, onMouseMove, onMouseLeave }) => {
440
+ let stateMods = {
441
+ selected: this.selection.isInstanceSelected(instance),
442
+ disabled: data.disabled,
443
+ selectable: !this.selection.isDummy,
444
+ [`color-${data.colorIndex}`]: data.colorIndex != null,
445
+ hover,
446
+ };
447
+
448
+ let d = createSvgArc(
449
+ segment.ox,
450
+ segment.oy,
451
+ data.r0 * segment.radiusMultiplier,
452
+ data.r * segment.radiusMultiplier,
453
+ segment.startAngle,
454
+ segment.endAngle,
455
+ data.br,
456
+ segment.gap,
457
+ );
458
+
459
+ return (
460
+ <g key={key} className={data.classNames}>
461
+ <path
462
+ className={this.CSS.element(this.baseClass, "slice", stateMods)}
463
+ style={data.style}
464
+ d={d}
465
+ onMouseMove={(e) => {
466
+ onMouseMove(e, instance);
467
+ tooltipMouseMove(e, instance, this.tooltip);
468
+ }}
469
+ onMouseLeave={(e) => {
470
+ onMouseLeave(e, instance);
471
+ tooltipMouseLeave(e, instance, this.tooltip);
472
+ }}
473
+ onClick={(e) => {
474
+ this.handleClick(e, instance);
475
+ }}
476
+ />
477
+ {this.renderChildren(context, instance)}
478
+ </g>
479
+ );
480
+ },
481
+ );
482
+ }
483
+
484
+ handleClick(e, instance) {
485
+ if (!this.selection.isDummy) {
486
+ this.selection.selectInstance(instance, {
487
+ toggle: e.ctrlKey,
488
+ });
489
+ e.stopPropagation();
490
+ e.preventDefault();
491
+ }
492
+ }
493
+ }
494
+
495
+ function move(x, y) {
496
+ return `M ${x} ${y}`;
497
+ }
498
+
499
+ function line(x, y) {
500
+ return `L ${x} ${y}`;
501
+ }
502
+
503
+ function z() {
504
+ return "Z";
505
+ }
506
+
507
+ function arc(rx, ry, xRotation, largeArc, sweep, x, y) {
508
+ return `A ${rx} ${ry} ${xRotation} ${largeArc} ${sweep} ${x} ${y}`;
509
+ }
510
+
511
+ function largeArcFlag(angle) {
512
+ return angle > Math.PI || angle < -Math.PI ? 1 : 0;
513
+ }
514
+
515
+ PieSlice.prototype.offset = 0;
516
+ PieSlice.prototype.r0 = 0;
517
+ PieSlice.prototype.r = 50;
518
+ PieSlice.prototype.percentageRadius = true;
519
+ PieSlice.prototype.baseClass = "pieslice";
520
+ PieSlice.prototype.legend = "legend";
521
+ PieSlice.prototype.active = true;
522
+ PieSlice.prototype.stack = "stack";
523
+ PieSlice.prototype.legendAction = "auto";
524
+ PieSlice.prototype.legendShape = "circle";
525
+ PieSlice.prototype.hoverChannel = "default";
526
+ PieSlice.prototype.styled = true;
527
+ PieSlice.prototype.br = 0;
528
+
529
+ Widget.alias("pie-chart", PieChart);