cx 26.2.2 → 26.2.3

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 (324) hide show
  1. package/build/charts/Chart.d.ts.map +1 -1
  2. package/build/charts/Chart.js +5 -4
  3. package/build/charts/ColumnBarBase.d.ts +3 -3
  4. package/build/charts/ColumnBarBase.d.ts.map +1 -1
  5. package/build/charts/ColumnBarBase.js +1 -1
  6. package/build/charts/Legend.d.ts.map +1 -1
  7. package/build/charts/Legend.js +11 -4
  8. package/build/charts/Marker.d.ts +3 -3
  9. package/build/charts/Marker.d.ts.map +1 -1
  10. package/build/charts/MarkerLine.d.ts +7 -7
  11. package/build/charts/MarkerLine.d.ts.map +1 -1
  12. package/build/charts/MarkerLine.js +14 -10
  13. package/build/charts/PieChart.d.ts +4 -4
  14. package/build/charts/PieChart.d.ts.map +1 -1
  15. package/build/charts/PieChart.js +36 -14
  16. package/build/charts/PieLabel.d.ts.map +1 -1
  17. package/build/charts/PieLabel.js +2 -1
  18. package/build/charts/RangeMarker.d.ts +3 -3
  19. package/build/charts/RangeMarker.d.ts.map +1 -1
  20. package/build/charts/RangeMarker.js +1 -1
  21. package/build/charts/axis/TimeAxis.d.ts +3 -3
  22. package/build/charts/axis/TimeAxis.d.ts.map +1 -1
  23. package/build/charts/axis/TimeAxis.js +70 -21
  24. package/build/charts/helpers/ValueAtFinder.d.ts +1 -1
  25. package/build/charts/helpers/ValueAtFinder.d.ts.map +1 -1
  26. package/build/charts/helpers/ValueAtFinder.js +5 -2
  27. package/build/data/StructuredSelector.js +3 -4
  28. package/build/data/createAccessorModelProxy.d.ts +6 -11
  29. package/build/data/createAccessorModelProxy.d.ts.map +1 -1
  30. package/build/data/createAccessorModelProxy.js +1 -3
  31. package/build/svg/Ellipse.d.ts +5 -4
  32. package/build/svg/Ellipse.d.ts.map +1 -1
  33. package/build/svg/Ellipse.js +9 -6
  34. package/build/svg/Line.d.ts +1 -0
  35. package/build/svg/Line.d.ts.map +1 -1
  36. package/build/svg/Line.js +4 -1
  37. package/build/svg/Text.d.ts +12 -6
  38. package/build/svg/Text.d.ts.map +1 -1
  39. package/build/svg/Text.js +12 -4
  40. package/build/ui/Controller.d.ts +2 -0
  41. package/build/ui/Controller.d.ts.map +1 -1
  42. package/build/ui/Controller.js +3 -0
  43. package/build/ui/HoverSync.d.ts.map +1 -1
  44. package/build/ui/HoverSync.js +7 -2
  45. package/build/ui/Prop.d.ts +1 -1
  46. package/build/ui/Prop.d.ts.map +1 -1
  47. package/build/ui/Text.d.ts +3 -3
  48. package/build/ui/Text.d.ts.map +1 -1
  49. package/build/ui/Text.js +5 -5
  50. package/build/ui/adapter/GroupAdapter.d.ts.map +1 -1
  51. package/build/ui/adapter/GroupAdapter.js +20 -10
  52. package/build/ui/app/History.js +1 -1
  53. package/build/widgets/List.d.ts.map +1 -1
  54. package/build/widgets/List.js +6 -7
  55. package/build/widgets/drag-drop/DropZone.d.ts +3 -3
  56. package/build/widgets/drag-drop/DropZone.d.ts.map +1 -1
  57. package/build/widgets/form/Calendar.d.ts.map +1 -1
  58. package/build/widgets/form/Calendar.js +30 -11
  59. package/build/widgets/form/ColorField.d.ts.map +1 -1
  60. package/build/widgets/form/ColorField.js +16 -7
  61. package/build/widgets/form/DateTimeField.d.ts.map +1 -1
  62. package/build/widgets/form/DateTimeField.js +23 -10
  63. package/build/widgets/form/Field.d.ts +2 -0
  64. package/build/widgets/form/Field.d.ts.map +1 -1
  65. package/build/widgets/form/Field.js +11 -5
  66. package/build/widgets/form/LookupField.d.ts +1 -1
  67. package/build/widgets/form/LookupField.d.ts.map +1 -1
  68. package/build/widgets/form/LookupField.js +6 -6
  69. package/build/widgets/form/MonthField.d.ts.map +1 -1
  70. package/build/widgets/form/MonthField.js +15 -7
  71. package/build/widgets/form/MonthPicker.d.ts +1 -2
  72. package/build/widgets/form/MonthPicker.d.ts.map +1 -1
  73. package/build/widgets/form/MonthPicker.js +84 -41
  74. package/build/widgets/form/NumberField.d.ts +2 -0
  75. package/build/widgets/form/NumberField.d.ts.map +1 -1
  76. package/build/widgets/form/NumberField.js +45 -15
  77. package/build/widgets/form/TextField.d.ts +1 -9
  78. package/build/widgets/form/TextField.d.ts.map +1 -1
  79. package/build/widgets/form/TextField.js +1 -1
  80. package/build/widgets/grid/Grid.d.ts +2 -2
  81. package/build/widgets/grid/Grid.d.ts.map +1 -1
  82. package/build/widgets/grid/Grid.js +14 -11
  83. package/build/widgets/grid/Pagination.d.ts.map +1 -1
  84. package/build/widgets/grid/Pagination.js +4 -4
  85. package/build/widgets/grid/TreeNode.d.ts.map +1 -1
  86. package/build/widgets/grid/TreeNode.js +10 -2
  87. package/build/widgets/icons/folder.d.ts.map +1 -1
  88. package/build/widgets/icons/folder.js +1 -0
  89. package/build/widgets/icons/forward.d.ts.map +1 -1
  90. package/build/widgets/icons/forward.js +4 -3
  91. package/build/widgets/icons/loading.d.ts.map +1 -1
  92. package/build/widgets/icons/loading.js +6 -5
  93. package/build/widgets/icons/square.d.ts.map +1 -1
  94. package/build/widgets/icons/square.js +3 -3
  95. package/build/widgets/index.d.ts +3 -1
  96. package/build/widgets/index.d.ts.map +1 -1
  97. package/build/widgets/index.js +3 -1
  98. package/build/widgets/overlay/ContextMenu.d.ts.map +1 -1
  99. package/build/widgets/overlay/ContextMenu.js +2 -0
  100. package/build/widgets/overlay/Dropdown.d.ts +2 -1
  101. package/build/widgets/overlay/Dropdown.d.ts.map +1 -1
  102. package/build/widgets/overlay/Dropdown.js +75 -20
  103. package/build/widgets/overlay/MsgBox.d.ts +1 -0
  104. package/build/widgets/overlay/MsgBox.d.ts.map +1 -1
  105. package/build/widgets/overlay/MsgBox.js +2 -2
  106. package/build/widgets/overlay/Overlay.d.ts +32 -2
  107. package/build/widgets/overlay/Overlay.d.ts.map +1 -1
  108. package/build/widgets/overlay/Overlay.js +47 -16
  109. package/build/widgets/overlay/Toast.d.ts +1 -1
  110. package/build/widgets/overlay/Toast.d.ts.map +1 -1
  111. package/build/widgets/overlay/Toast.js +4 -1
  112. package/build/widgets/overlay/Tooltip.d.ts +6 -0
  113. package/build/widgets/overlay/Tooltip.d.ts.map +1 -1
  114. package/build/widgets/overlay/Tooltip.js +24 -9
  115. package/build/widgets/overlay/Window.d.ts.map +1 -1
  116. package/build/widgets/overlay/Window.js +24 -9
  117. package/dist/charts.css +325 -272
  118. package/dist/charts.js +11 -5
  119. package/dist/data.js +2 -2
  120. package/dist/manifest.js +821 -809
  121. package/dist/svg.css +14 -8
  122. package/dist/svg.js +9 -1
  123. package/dist/ui.js +29 -16
  124. package/dist/widgets.css +997 -294
  125. package/dist/widgets.js +319 -126
  126. package/package.json +1 -1
  127. package/src/charts/Bar.scss +13 -10
  128. package/src/charts/BarGraph.scss +31 -29
  129. package/src/charts/BubbleGraph.scss +11 -8
  130. package/src/charts/Chart.ts +5 -3
  131. package/src/charts/Column.scss +13 -10
  132. package/src/charts/ColumnBarBase.tsx +255 -230
  133. package/src/charts/ColumnGraph.scss +13 -11
  134. package/src/charts/Gridlines.scss +10 -8
  135. package/src/charts/Legend.scss +57 -50
  136. package/src/charts/Legend.tsx +257 -213
  137. package/src/charts/LegendEntry.scss +35 -29
  138. package/src/charts/LineGraph.scss +28 -25
  139. package/src/charts/Marker.scss +12 -10
  140. package/src/charts/Marker.tsx +3 -2
  141. package/src/charts/MarkerLine.scss +11 -8
  142. package/src/charts/MarkerLine.tsx +196 -177
  143. package/src/charts/PieChart.scss +12 -9
  144. package/src/charts/PieChart.tsx +717 -591
  145. package/src/charts/PieLabel.tsx +99 -81
  146. package/src/charts/Range.scss +11 -8
  147. package/src/charts/RangeMarker.tsx +204 -187
  148. package/src/charts/ScatterGraph.scss +12 -9
  149. package/src/charts/axis/Axis.scss +6 -5
  150. package/src/charts/axis/CategoryAxis.scss +10 -8
  151. package/src/charts/axis/NumericAxis.scss +9 -6
  152. package/src/charts/axis/TimeAxis.scss +9 -6
  153. package/src/charts/axis/TimeAxis.tsx +753 -637
  154. package/src/charts/axis/index.scss +4 -5
  155. package/src/charts/axis/variables.scss +4 -2
  156. package/src/charts/helpers/ValueAtFinder.ts +19 -5
  157. package/src/charts/index.scss +16 -19
  158. package/src/charts/maps.scss +0 -0
  159. package/src/charts/palette.scss +11 -31
  160. package/src/charts/palette.variables.scss +23 -0
  161. package/src/charts/variables.scss +35 -3
  162. package/src/data/StructuredSelector.ts +2 -2
  163. package/src/data/createAccessorModelProxy.ts +66 -74
  164. package/src/index.scss +5 -6
  165. package/src/maps.scss +5 -0
  166. package/src/svg/Ellipse.tsx +62 -55
  167. package/src/svg/Line.tsx +57 -42
  168. package/src/svg/Svg.scss +6 -6
  169. package/src/svg/Text.scss +19 -0
  170. package/src/svg/Text.tsx +172 -116
  171. package/src/svg/index.scss +3 -2
  172. package/src/svg/maps.scss +0 -0
  173. package/src/svg/variables.scss +0 -0
  174. package/src/ui/Container.spec.ts +59 -0
  175. package/src/ui/Controller.spec.tsx +30 -0
  176. package/src/ui/Controller.ts +5 -0
  177. package/src/ui/HoverSync.tsx +179 -147
  178. package/src/ui/Prop.ts +1 -1
  179. package/src/ui/Text.ts +12 -9
  180. package/src/ui/adapter/GroupAdapter.spec.ts +42 -0
  181. package/src/ui/adapter/GroupAdapter.ts +25 -14
  182. package/src/ui/app/History.ts +1 -1
  183. package/src/ui/index.scss +1 -1
  184. package/src/ui/layout/LabelsLeftLayout.scss +5 -7
  185. package/src/ui/layout/LabelsTopLayout.scss +4 -6
  186. package/src/ui/layout/index.scss +2 -3
  187. package/src/ui/maps.scss +0 -0
  188. package/src/ui/variables.scss +1 -2
  189. package/src/util/index.scss +4 -2
  190. package/src/util/maps.scss +1 -0
  191. package/src/util/scss/besm.scss +15 -0
  192. package/src/util/scss/calc.scss +103 -11
  193. package/src/util/scss/defaults.scss +24 -0
  194. package/src/util/scss/elements.scss +78 -0
  195. package/src/util/scss/global.scss +15 -0
  196. package/src/util/scss/include.scss +17 -9
  197. package/src/util/scss/index.scss +1 -9
  198. package/src/util/scss/maps.scss +2 -0
  199. package/src/util/scss/pad-size.scss +9 -0
  200. package/src/util/scss/padding.scss +6 -0
  201. package/src/util/scss/screen-size.scss +5 -0
  202. package/src/util/scss/variables.scss +6 -0
  203. package/src/util/variables.scss +1 -0
  204. package/src/variables.scss +5 -217
  205. package/src/widgets/Button.maps.scss +103 -0
  206. package/src/widgets/Button.scss +33 -9
  207. package/src/widgets/Button.variables.scss +8 -104
  208. package/src/widgets/CxCredit.scss +2 -0
  209. package/src/widgets/FlexBox.scss +16 -11
  210. package/src/widgets/Heading.scss +6 -0
  211. package/src/widgets/HighlightedSearchText.scss +8 -1
  212. package/src/widgets/Icon.scss +6 -0
  213. package/src/widgets/List.scss +7 -0
  214. package/src/widgets/List.tsx +6 -7
  215. package/src/widgets/ProgressBar.scss +9 -0
  216. package/src/widgets/Resizer.scss +9 -7
  217. package/src/widgets/Section.scss +53 -56
  218. package/src/widgets/animations.scss +4 -2
  219. package/src/widgets/box.scss +47 -0
  220. package/src/widgets/drag-drop/DragClone.scss +12 -4
  221. package/src/widgets/drag-drop/DragHandle.scss +12 -6
  222. package/src/widgets/drag-drop/DragSource.scss +12 -6
  223. package/src/widgets/drag-drop/DropZone.scss +9 -0
  224. package/src/widgets/drag-drop/DropZone.tsx +3 -3
  225. package/src/widgets/drag-drop/index.scss +4 -4
  226. package/src/widgets/drag-drop/maps.scss +7 -0
  227. package/src/widgets/drag-drop/variables.scss +8 -5
  228. package/src/widgets/form/Calendar.maps.scss +54 -0
  229. package/src/widgets/form/Calendar.scss +49 -11
  230. package/src/widgets/form/Calendar.tsx +755 -653
  231. package/src/widgets/form/Calendar.variables.scss +3 -46
  232. package/src/widgets/form/Checkbox.maps.scss +34 -0
  233. package/src/widgets/form/Checkbox.scss +14 -3
  234. package/src/widgets/form/Checkbox.variables.scss +4 -36
  235. package/src/widgets/form/ColorField.scss +21 -2
  236. package/src/widgets/form/ColorField.tsx +485 -431
  237. package/src/widgets/form/ColorPicker.maps.scss +21 -0
  238. package/src/widgets/form/ColorPicker.scss +26 -9
  239. package/src/widgets/form/ColorPicker.variables.scss +3 -16
  240. package/src/widgets/form/DateTimeField.scss +54 -21
  241. package/src/widgets/form/DateTimeField.tsx +697 -615
  242. package/src/widgets/form/DateTimePicker.scss +14 -4
  243. package/src/widgets/form/Field.maps.scss +122 -0
  244. package/src/widgets/form/Field.scss +54 -18
  245. package/src/widgets/form/Field.tsx +611 -504
  246. package/src/widgets/form/Field.variables.scss +46 -0
  247. package/src/widgets/form/HelpText.scss +8 -5
  248. package/src/widgets/form/Label.scss +10 -3
  249. package/src/widgets/form/LookupField.maps.scss +26 -0
  250. package/src/widgets/form/LookupField.scss +54 -24
  251. package/src/widgets/form/LookupField.tsx +25 -21
  252. package/src/widgets/form/MonthField.scss +48 -26
  253. package/src/widgets/form/MonthField.tsx +645 -567
  254. package/src/widgets/form/MonthPicker.maps.scss +50 -0
  255. package/src/widgets/form/MonthPicker.scss +44 -35
  256. package/src/widgets/form/MonthPicker.tsx +954 -724
  257. package/src/widgets/form/MonthPicker.variables.scss +24 -0
  258. package/src/widgets/form/NumberField.scss +19 -2
  259. package/src/widgets/form/NumberField.tsx +576 -466
  260. package/src/widgets/form/Radio.maps.scss +36 -0
  261. package/src/widgets/form/Radio.scss +12 -2
  262. package/src/widgets/form/Radio.variables.scss +3 -42
  263. package/src/widgets/form/Select.scss +25 -9
  264. package/src/widgets/form/Slider.scss +23 -14
  265. package/src/widgets/form/Switch.scss +18 -8
  266. package/src/widgets/form/TextArea.scss +14 -1
  267. package/src/widgets/form/TextField.scss +24 -3
  268. package/src/widgets/form/TextField.tsx +9 -21
  269. package/src/widgets/form/UploadButton.scss +14 -6
  270. package/src/widgets/form/ValidationError.scss +10 -6
  271. package/src/widgets/form/Wheel.scss +14 -4
  272. package/src/widgets/form/index.scss +22 -24
  273. package/src/widgets/form/maps.scss +81 -0
  274. package/src/widgets/form/variables.scss +111 -355
  275. package/src/widgets/grid/Grid.scss +19 -2
  276. package/src/widgets/grid/Grid.spec.ts +42 -0
  277. package/src/widgets/grid/Grid.tsx +18 -13
  278. package/src/widgets/grid/Pagination.scss +11 -2
  279. package/src/widgets/grid/Pagination.tsx +110 -102
  280. package/src/widgets/grid/TreeNode.scss +25 -8
  281. package/src/widgets/grid/TreeNode.tsx +127 -116
  282. package/src/widgets/grid/index.scss +3 -4
  283. package/src/widgets/grid/maps.scss +110 -0
  284. package/src/widgets/grid/variables.scss +48 -137
  285. package/src/widgets/icons/folder.tsx +1 -2
  286. package/src/widgets/icons/forward.tsx +23 -20
  287. package/src/widgets/icons/loading.tsx +22 -19
  288. package/src/widgets/icons/square.tsx +20 -17
  289. package/src/widgets/index.scss +16 -16
  290. package/src/widgets/index.ts +63 -58
  291. package/src/widgets/lists.scss +42 -0
  292. package/src/widgets/maps.scss +139 -0
  293. package/src/widgets/nav/Link.scss +14 -1
  294. package/src/widgets/nav/Menu.scss +13 -7
  295. package/src/widgets/nav/Menu.variables.scss +1 -12
  296. package/src/widgets/nav/MenuItem.scss +21 -6
  297. package/src/widgets/nav/Scroller.scss +11 -2
  298. package/src/widgets/nav/Tab.maps.scss +78 -0
  299. package/src/widgets/nav/Tab.scss +12 -6
  300. package/src/widgets/nav/Tab.variables.scss +7 -76
  301. package/src/widgets/nav/cover.scss +6 -4
  302. package/src/widgets/nav/index.scss +6 -6
  303. package/src/widgets/nav/maps.scss +32 -0
  304. package/src/widgets/nav/variables.scss +4 -11
  305. package/src/widgets/overlay/ContextMenu.ts +3 -0
  306. package/src/widgets/overlay/Dropdown.scss +47 -16
  307. package/src/widgets/overlay/Dropdown.tsx +851 -676
  308. package/src/widgets/overlay/MsgBox.tsx +125 -111
  309. package/src/widgets/overlay/Overlay.scss +60 -40
  310. package/src/widgets/overlay/Overlay.tsx +948 -800
  311. package/src/widgets/overlay/Toast.scss +42 -34
  312. package/src/widgets/overlay/Toast.ts +11 -1
  313. package/src/widgets/overlay/Tooltip.scss +27 -96
  314. package/src/widgets/overlay/Tooltip.tsx +376 -309
  315. package/src/widgets/overlay/Window.maps.scss +51 -0
  316. package/src/widgets/overlay/Window.scss +17 -17
  317. package/src/widgets/overlay/Window.tsx +291 -236
  318. package/src/widgets/overlay/Window.variables.scss +2 -43
  319. package/src/widgets/overlay/index.d.ts +11 -11
  320. package/src/widgets/overlay/index.scss +6 -15
  321. package/src/widgets/overlay/maps.scss +44 -0
  322. package/src/widgets/overlay/variables.scss +11 -42
  323. package/src/widgets/variables.scss +33 -117
  324. package/src/global.scss +0 -14
@@ -1,367 +1,448 @@
1
1
  /** @jsxImportSource react */
2
2
 
3
3
  import { Widget, VDOM, WidgetConfig } from "../ui/Widget";
4
- import { Container, ContainerConfig, StyledContainerConfig } from "../ui/Container";
5
- import { BoundedObject, BoundedObjectConfig, BoundedObjectInstance } from "../svg/BoundedObject";
4
+ import {
5
+ Container,
6
+ ContainerConfig,
7
+ StyledContainerConfig,
8
+ } from "../ui/Container";
9
+ import {
10
+ BoundedObject,
11
+ BoundedObjectConfig,
12
+ BoundedObjectInstance,
13
+ } from "../svg/BoundedObject";
6
14
  import { Rect } from "../svg/util/Rect";
7
15
  import { Selection, SimpleSelection } from "../ui/selection/Selection";
8
16
  import type { KeySelection } from "../ui/selection/KeySelection";
9
17
  import type { PropertySelection } from "../ui/selection/PropertySelection";
10
- import { tooltipMouseMove, tooltipMouseLeave, TooltipParentInstance } from "../widgets/overlay/tooltip-ops";
18
+ import {
19
+ tooltipMouseMove,
20
+ tooltipMouseLeave,
21
+ TooltipParentInstance,
22
+ } from "../widgets/overlay/tooltip-ops";
11
23
  import { isNumber } from "../util/isNumber";
12
24
  import { shallowEquals } from "../util/shallowEquals";
13
25
  import { withHoverSync } from "../ui/HoverSync";
14
26
  import { Instance } from "../ui/Instance";
15
27
  import { RenderingContext } from "../ui/RenderingContext";
16
- import { NumberProp, BooleanProp, StringProp } from "../ui/Prop";
28
+ import { NumberProp, BooleanProp, StringProp, Prop } from "../ui/Prop";
17
29
  import { CreateConfig } from "../util/Component";
18
30
 
19
31
  export interface PieChartConfig extends BoundedObjectConfig {
20
- /** Total angle of the pie chart in degrees. Default is `360`. */
21
- angle?: NumberProp;
32
+ /** Total angle of the pie chart in degrees. Default is `360`. */
33
+ angle?: NumberProp;
22
34
 
23
- /** Starting angle in degrees. Default is `0`. */
24
- startAngle?: NumberProp;
35
+ /** Starting angle in degrees. Default is `0`. */
36
+ startAngle?: NumberProp;
25
37
 
26
- /** Set to `true` for clockwise direction. */
27
- clockwise?: BooleanProp;
38
+ /** Set to `true` for clockwise direction. */
39
+ clockwise?: BooleanProp;
28
40
 
29
- /** Gap between slices in pixels. Default is `0`. */
30
- gap?: NumberProp;
41
+ /** Gap between slices in pixels. Default is `0`. */
42
+ gap?: NumberProp;
31
43
  }
32
44
 
33
45
  export interface PieChartInstance extends BoundedObjectInstance {
34
- pie: PieCalculator;
46
+ pie: PieCalculator;
35
47
  }
36
48
 
37
49
  export class PieChart extends BoundedObject {
38
- declare angle: number;
39
- declare startAngle: number;
40
- declare gap: number;
41
-
42
- constructor(config: PieChartConfig) {
43
- super(config);
44
- }
45
-
46
- declareData(...args: any[]): void {
47
- super.declareData(...args, {
48
- angle: undefined,
49
- startAngle: undefined,
50
- clockwise: undefined,
51
- gap: undefined,
52
- });
53
- }
54
-
55
- explore(context: RenderingContext, instance: PieChartInstance): void {
56
- if (!instance.pie) instance.pie = new PieCalculator();
57
- let { data } = instance;
58
- instance.pie.reset(data.angle, data.startAngle, data.clockwise, data.gap);
59
-
60
- context.push("pie", instance.pie);
61
- super.explore(context, instance);
62
- }
63
-
64
- exploreCleanup(context: RenderingContext, instance: PieChartInstance): void {
65
- context.pop("pie");
66
- }
67
-
68
- prepare(context: RenderingContext, instance: PieChartInstance): void {
69
- this.prepareBounds(context, instance);
70
- let { data, pie } = instance;
71
- pie.measure(data.bounds);
72
- let hash = pie.hash();
73
- instance.cache("hash", hash);
74
- pie.shouldUpdate = !shallowEquals(hash, instance.cached.hash);
75
- if (!pie.shouldUpdate) instance.markShouldUpdate(context);
76
- super.prepare(context, instance);
77
- }
50
+ declare angle: number;
51
+ declare startAngle: number;
52
+ declare gap: number;
53
+
54
+ constructor(config: PieChartConfig) {
55
+ super(config);
56
+ }
57
+
58
+ declareData(...args: any[]): void {
59
+ super.declareData(...args, {
60
+ angle: undefined,
61
+ startAngle: undefined,
62
+ clockwise: undefined,
63
+ gap: undefined,
64
+ });
65
+ }
66
+
67
+ explore(context: RenderingContext, instance: PieChartInstance): void {
68
+ if (!instance.pie) instance.pie = new PieCalculator();
69
+ let { data } = instance;
70
+ instance.pie.reset(data.angle, data.startAngle, data.clockwise, data.gap);
71
+
72
+ context.push("pie", instance.pie);
73
+ super.explore(context, instance);
74
+ }
75
+
76
+ exploreCleanup(context: RenderingContext, instance: PieChartInstance): void {
77
+ context.pop("pie");
78
+ }
79
+
80
+ prepare(context: RenderingContext, instance: PieChartInstance): void {
81
+ this.prepareBounds(context, instance);
82
+ let { data, pie } = instance;
83
+ pie.measure(data.bounds);
84
+ let hash = pie.hash();
85
+ instance.cache("hash", hash);
86
+ pie.shouldUpdate = !shallowEquals(hash, instance.cached.hash);
87
+ if (!pie.shouldUpdate) instance.markShouldUpdate(context);
88
+ super.prepare(context, instance);
89
+ }
78
90
  }
79
91
 
80
92
  PieChart.prototype.anchors = "0 1 1 0";
81
93
 
82
94
  interface PieStack {
83
- total: number;
84
- r0s: number[] | null;
85
- r0ps: number[] | null;
86
- gap: number;
87
- angleFactor: number;
88
- lastAngle: number;
95
+ total: number;
96
+ r0s: number[] | null;
97
+ r0ps: number[] | null;
98
+ gap: number;
99
+ angleFactor: number;
100
+ lastAngle: number;
89
101
  }
90
102
 
91
103
  export interface PieSegment {
92
- startAngle: number;
93
- endAngle: number;
94
- angle: number;
95
- midAngle: number;
96
- gap: number;
97
- cx: number;
98
- cy: number;
99
- R: number;
100
- ox?: number;
101
- oy?: number;
102
- radiusMultiplier?: number;
104
+ startAngle: number;
105
+ endAngle: number;
106
+ angle: number;
107
+ midAngle: number;
108
+ gap: number;
109
+ cx: number;
110
+ cy: number;
111
+ R: number;
112
+ ox?: number;
113
+ oy?: number;
114
+ radiusMultiplier?: number;
103
115
  }
104
116
 
105
117
  class PieCalculator {
106
- angleTotal: number = 0;
107
- startAngle: number = 0;
108
- clockwise: boolean = false;
109
- gap: number = 0;
110
- stacks: Record<string, PieStack> = {};
111
- cx: number = 0;
112
- cy: number = 0;
113
- R: number = 0;
114
- shouldUpdate: boolean = false;
115
-
116
- reset(angle: number, startAngle: number, clockwise: boolean, gap: number): void {
117
- if (angle == 360) angle = 359.99; // really hacky way to draw full circles
118
- this.angleTotal = (angle / 180) * Math.PI;
119
- this.startAngle = (startAngle / 180) * Math.PI;
120
- this.clockwise = clockwise;
121
- this.gap = gap;
122
- this.stacks = {};
123
- }
124
-
125
- acknowledge(stack: string, value: number, r: number, r0: number, percentageRadius: boolean): void {
126
- let s = this.stacks[stack];
127
- if (!s)
128
- s = this.stacks[stack] = {
129
- total: 0,
130
- r0s: this.gap > 0 ? [] : null,
131
- r0ps: this.gap > 0 ? [] : null,
132
- gap: 0,
133
- angleFactor: 0,
134
- lastAngle: 0,
135
- };
136
- if (value > 0) {
137
- s.total += value;
138
- if (this.gap > 0 && r0 > 0)
139
- if (percentageRadius) s.r0ps!.push(r0);
140
- else s.r0s!.push(r0);
141
- }
142
- }
143
-
144
- hash(): Record<string, any> {
145
- return {
146
- angleTotal: this.angleTotal,
147
- startAngle: this.startAngle,
148
- clockwise: this.clockwise,
149
- stacks: Object.keys(this.stacks)
150
- .map((s) => `${this.stacks[s].angleFactor}`)
151
- .join(":"),
152
- cx: this.cx,
153
- cy: this.cy,
154
- R: this.R,
155
- gap: this.gap,
118
+ angleTotal: number = 0;
119
+ startAngle: number = 0;
120
+ clockwise: boolean = false;
121
+ gap: number = 0;
122
+ stacks: Record<string, PieStack> = {};
123
+ cx: number = 0;
124
+ cy: number = 0;
125
+ R: number = 0;
126
+ shouldUpdate: boolean = false;
127
+
128
+ reset(
129
+ angle: number,
130
+ startAngle: number,
131
+ clockwise: boolean,
132
+ gap: number,
133
+ ): void {
134
+ if (angle == 360) angle = 359.99; // really hacky way to draw full circles
135
+ this.angleTotal = (angle / 180) * Math.PI;
136
+ this.startAngle = (startAngle / 180) * Math.PI;
137
+ this.clockwise = clockwise;
138
+ this.gap = gap;
139
+ this.stacks = {};
140
+ }
141
+
142
+ acknowledge(
143
+ stack: string,
144
+ value: number,
145
+ r: number,
146
+ r0: number,
147
+ percentageRadius: boolean,
148
+ ): void {
149
+ let s = this.stacks[stack];
150
+ if (!s)
151
+ s = this.stacks[stack] = {
152
+ total: 0,
153
+ r0s: this.gap > 0 ? [] : null,
154
+ r0ps: this.gap > 0 ? [] : null,
155
+ gap: 0,
156
+ angleFactor: 0,
157
+ lastAngle: 0,
156
158
  };
157
- }
158
-
159
- measure(rect: Rect): void {
160
- this.R = Math.max(0, Math.min(rect.width(), rect.height())) / 2;
161
- for (let s in this.stacks) {
162
- let stack = this.stacks[s];
163
- let gapAngleTotal = 0;
164
- stack.gap = this.gap;
165
- if (this.gap > 0) {
166
- // gap cannot be larger of two times the smallest r0
167
- for (let index = 0; index < stack.r0s!.length; index++)
168
- if (2 * stack.r0s![index] < stack.gap) stack.gap = 2 * stack.r0s![index];
169
- for (let index = 0; index < stack.r0ps!.length; index++) {
170
- let r0 = (stack.r0ps![index] * this.R) / 100;
171
- if (2 * r0 < stack.gap) stack.gap = 2 * r0;
172
- }
173
- }
174
- while (stack.gap > 0) {
175
- for (let index = 0; index < stack.r0s!.length; index++)
176
- gapAngleTotal += 2 * Math.asin(stack.gap / stack.r0s![index] / 2);
177
-
178
- for (let index = 0; index < stack.r0ps!.length; index++)
179
- gapAngleTotal += 2 * Math.asin(stack.gap / ((stack.r0ps![index] * this.R) / 100) / 2);
180
-
181
- if (gapAngleTotal < 0.25 * this.angleTotal) break;
182
- stack.gap = stack.gap * 0.95;
183
- gapAngleTotal = 0;
184
- }
185
- if (gapAngleTotal == 0) stack.gap = 0;
186
- stack.angleFactor = stack.total > 0 ? (this.angleTotal - gapAngleTotal) / stack.total : 0;
187
- stack.lastAngle = this.startAngle;
159
+ if (value > 0) {
160
+ s.total += value;
161
+ if (this.gap > 0 && r0 > 0)
162
+ if (percentageRadius) s.r0ps!.push(r0);
163
+ else s.r0s!.push(r0);
164
+ }
165
+ }
166
+
167
+ hash(): Record<string, any> {
168
+ return {
169
+ angleTotal: this.angleTotal,
170
+ startAngle: this.startAngle,
171
+ clockwise: this.clockwise,
172
+ stacks: Object.keys(this.stacks)
173
+ .map((s) => `${this.stacks[s].angleFactor}`)
174
+ .join(":"),
175
+ cx: this.cx,
176
+ cy: this.cy,
177
+ R: this.R,
178
+ gap: this.gap,
179
+ };
180
+ }
181
+
182
+ measure(rect: Rect): void {
183
+ this.R = Math.max(0, Math.min(rect.width(), rect.height())) / 2;
184
+ for (let s in this.stacks) {
185
+ let stack = this.stacks[s];
186
+ let gapAngleTotal = 0;
187
+ stack.gap = this.gap;
188
+ if (this.gap > 0) {
189
+ // gap cannot be larger of two times the smallest r0
190
+ for (let index = 0; index < stack.r0s!.length; index++)
191
+ if (2 * stack.r0s![index] < stack.gap)
192
+ stack.gap = 2 * stack.r0s![index];
193
+ for (let index = 0; index < stack.r0ps!.length; index++) {
194
+ let r0 = (stack.r0ps![index] * this.R) / 100;
195
+ if (2 * r0 < stack.gap) stack.gap = 2 * r0;
196
+ }
188
197
  }
189
- this.cx = (rect.l + rect.r) / 2;
190
- this.cy = (rect.t + rect.b) / 2;
191
- }
192
-
193
- map(stack: string, value: number, r: number, r0: number, percentageRadius: boolean): PieSegment {
194
- if (percentageRadius) {
195
- r = (r * this.R) / 100;
196
- r0 = (r0 * this.R) / 100;
198
+ while (stack.gap > 0) {
199
+ for (let index = 0; index < stack.r0s!.length; index++)
200
+ gapAngleTotal += 2 * Math.asin(stack.gap / stack.r0s![index] / 2);
201
+
202
+ for (let index = 0; index < stack.r0ps!.length; index++)
203
+ gapAngleTotal +=
204
+ 2 *
205
+ Math.asin(stack.gap / ((stack.r0ps![index] * this.R) / 100) / 2);
206
+
207
+ if (gapAngleTotal < 0.25 * this.angleTotal) break;
208
+ stack.gap = stack.gap * 0.95;
209
+ gapAngleTotal = 0;
197
210
  }
198
- let s = this.stacks[stack];
199
- let angle = value * s.angleFactor;
200
- let startAngle = s.lastAngle;
201
- let clockFactor = this.clockwise ? -1 : 1;
202
- let gapAngle = r0 > 0 && s.gap > 0 ? 2 * Math.asin(s.gap / r0 / 2) : 0;
203
- s.lastAngle += clockFactor * (angle + gapAngle);
204
- let endAngle = startAngle + clockFactor * (angle + gapAngle);
205
-
206
- return {
207
- startAngle,
208
- endAngle: startAngle + clockFactor * (angle + gapAngle),
209
- angle,
210
- midAngle: (startAngle + endAngle) / 2,
211
- gap: s.gap,
212
- cx: this.cx,
213
- cy: this.cy,
214
- R: this.R,
215
- };
216
- }
211
+ if (gapAngleTotal == 0) stack.gap = 0;
212
+ stack.angleFactor =
213
+ stack.total > 0 ? (this.angleTotal - gapAngleTotal) / stack.total : 0;
214
+ stack.lastAngle = this.startAngle;
215
+ }
216
+ this.cx = (rect.l + rect.r) / 2;
217
+ this.cy = (rect.t + rect.b) / 2;
218
+ }
219
+
220
+ map(
221
+ stack: string,
222
+ value: number,
223
+ r: number,
224
+ r0: number,
225
+ percentageRadius: boolean,
226
+ ): PieSegment {
227
+ if (percentageRadius) {
228
+ r = (r * this.R) / 100;
229
+ r0 = (r0 * this.R) / 100;
230
+ }
231
+ let s = this.stacks[stack];
232
+ let angle = value * s.angleFactor;
233
+ let startAngle = s.lastAngle;
234
+ let clockFactor = this.clockwise ? -1 : 1;
235
+ let gapAngle = r0 > 0 && s.gap > 0 ? 2 * Math.asin(s.gap / r0 / 2) : 0;
236
+ s.lastAngle += clockFactor * (angle + gapAngle);
237
+ let endAngle = startAngle + clockFactor * (angle + gapAngle);
238
+
239
+ return {
240
+ startAngle,
241
+ endAngle: startAngle + clockFactor * (angle + gapAngle),
242
+ angle,
243
+ midAngle: (startAngle + endAngle) / 2,
244
+ gap: s.gap,
245
+ cx: this.cx,
246
+ cy: this.cy,
247
+ R: this.R,
248
+ };
249
+ }
217
250
  }
218
251
 
219
252
  function createSvgArc(
220
- cx: number,
221
- cy: number,
222
- r0: number = 0,
223
- r: number,
224
- startAngle: number,
225
- endAngle: number,
226
- br: number = 0,
227
- gap: number = 0,
253
+ cx: number,
254
+ cy: number,
255
+ r0: number = 0,
256
+ r: number,
257
+ startAngle: number,
258
+ endAngle: number,
259
+ br: number = 0,
260
+ gap: number = 0,
228
261
  ): string {
229
- let gap2 = gap / 2;
230
-
231
- if (startAngle > endAngle) {
232
- let s = startAngle;
233
- startAngle = endAngle;
234
- endAngle = s;
235
- }
236
-
237
- let path = [];
238
- // limit br size based on r and r0
239
- if (br > (r - r0) / 2) br = (r - r0) / 2;
240
-
241
- if (br > 0) {
242
- if (r0 > 0) {
243
- let innerBr = br;
244
- let innerSmallArcAngle = Math.asin((br + gap2) / (r0 + br));
245
-
246
- // adjust br according to the available area
247
- if (innerSmallArcAngle > (endAngle - startAngle) / 2) {
248
- innerSmallArcAngle = (endAngle - startAngle) / 2;
249
- let sin = Math.sin(innerSmallArcAngle);
250
- innerBr = Math.max((r0 * sin - gap2) / (1 - sin), 0);
251
- }
252
-
253
- let innerHipDiagonal = (r0 + innerBr) * Math.cos(innerSmallArcAngle);
254
-
255
- let innerSmallArc1XFrom = cx + Math.cos(endAngle) * innerHipDiagonal + Math.cos(endAngle - Math.PI / 2) * gap2;
256
- let innerSmallArc1YFrom = cy - Math.sin(endAngle) * innerHipDiagonal - Math.sin(endAngle - Math.PI / 2) * gap2;
257
-
258
- // move from the first small inner arc
259
- path.push(move(innerSmallArc1XFrom, innerSmallArc1YFrom));
260
-
261
- let innerSmallArc1XTo = cx + Math.cos(endAngle - innerSmallArcAngle) * r0;
262
- let innerSmallArc1YTo = cy - Math.sin(endAngle - innerSmallArcAngle) * r0;
263
-
264
- // add first small inner arc
265
- path.push(arc(innerBr, innerBr, 0, 0, 0, innerSmallArc1XTo, innerSmallArc1YTo));
266
-
267
- // SECOND ARC
268
-
269
- let innerArcXTo = cx + Math.cos(startAngle + innerSmallArcAngle) * r0;
270
- let innerArcYTo = cy - Math.sin(startAngle + innerSmallArcAngle) * r0;
271
- // add large inner arc
272
- path.push(
273
- arc(
274
- r0,
275
- r0,
276
- 0,
277
- largeArcFlag(endAngle - innerSmallArcAngle - startAngle - innerSmallArcAngle),
278
- 1,
279
- innerArcXTo,
280
- innerArcYTo,
281
- ),
282
- );
283
-
284
- let innerSmallArc2XTo =
285
- cx + Math.cos(startAngle) * innerHipDiagonal + Math.cos(startAngle + Math.PI / 2) * gap2;
286
- let innerSmallArc2YTo =
287
- cy - Math.sin(startAngle) * innerHipDiagonal - Math.sin(startAngle + Math.PI / 2) * gap2;
288
- // add second small inner arc
289
- path.push(arc(innerBr, innerBr, 0, 0, 0, innerSmallArc2XTo, innerSmallArc2YTo));
290
- } else {
291
- path.push(move(cx, cy));
262
+ let gap2 = gap / 2;
263
+
264
+ if (startAngle > endAngle) {
265
+ let s = startAngle;
266
+ startAngle = endAngle;
267
+ endAngle = s;
268
+ }
269
+
270
+ let path = [];
271
+ // limit br size based on r and r0
272
+ if (br > (r - r0) / 2) br = (r - r0) / 2;
273
+
274
+ if (br > 0) {
275
+ if (r0 > 0) {
276
+ let innerBr = br;
277
+ let innerSmallArcAngle = Math.asin((br + gap2) / (r0 + br));
278
+
279
+ // adjust br according to the available area
280
+ if (innerSmallArcAngle > (endAngle - startAngle) / 2) {
281
+ innerSmallArcAngle = (endAngle - startAngle) / 2;
282
+ let sin = Math.sin(innerSmallArcAngle);
283
+ innerBr = Math.max((r0 * sin - gap2) / (1 - sin), 0);
292
284
  }
293
285
 
294
- let outerBr = br;
295
- let outerSmallArcAngle = Math.asin((br + gap2) / (r - br));
296
-
297
- // tweak br according to the available area
298
- if (outerSmallArcAngle > (endAngle - startAngle) / 2) {
299
- outerSmallArcAngle = (endAngle - startAngle) / 2;
300
- let sin = Math.sin(outerSmallArcAngle);
301
- outerBr = Math.max((r * sin - gap2) / (1 + sin), 0);
302
- }
286
+ let innerHipDiagonal = (r0 + innerBr) * Math.cos(innerSmallArcAngle);
303
287
 
304
- let outerHipDiagonal = Math.cos(outerSmallArcAngle) * (r - outerBr);
288
+ let innerSmallArc1XFrom =
289
+ cx +
290
+ Math.cos(endAngle) * innerHipDiagonal +
291
+ Math.cos(endAngle - Math.PI / 2) * gap2;
292
+ let innerSmallArc1YFrom =
293
+ cy -
294
+ Math.sin(endAngle) * innerHipDiagonal -
295
+ Math.sin(endAngle - Math.PI / 2) * gap2;
305
296
 
306
- let outerSmallArc1XFrom =
307
- cx + Math.cos(startAngle) * outerHipDiagonal + Math.cos(startAngle + Math.PI / 2) * gap2;
308
- let outerSmallArc1YFrom =
309
- cy - Math.sin(startAngle) * outerHipDiagonal - Math.sin(startAngle + Math.PI / 2) * gap2;
297
+ // move from the first small inner arc
298
+ path.push(move(innerSmallArc1XFrom, innerSmallArc1YFrom));
310
299
 
311
- let outerSmallArc1XTo = cx + Math.cos(startAngle + outerSmallArcAngle) * r;
312
- let outerSmallArc1YTo = cy - Math.sin(startAngle + outerSmallArcAngle) * r;
300
+ let innerSmallArc1XTo = cx + Math.cos(endAngle - innerSmallArcAngle) * r0;
301
+ let innerSmallArc1YTo = cy - Math.sin(endAngle - innerSmallArcAngle) * r0;
313
302
 
314
- let outerLargeArcXTo = cx + Math.cos(endAngle - outerSmallArcAngle) * r;
315
- let outerLargeArcYTo = cy - Math.sin(endAngle - outerSmallArcAngle) * r;
303
+ // add first small inner arc
304
+ path.push(
305
+ arc(innerBr, innerBr, 0, 0, 0, innerSmallArc1XTo, innerSmallArc1YTo),
306
+ );
316
307
 
317
- let outerSmallArc2XTo = cx + Math.cos(endAngle) * outerHipDiagonal + Math.cos(endAngle - Math.PI / 2) * gap2;
318
- let outerSmallArc2YTo = cy - Math.sin(endAngle) * outerHipDiagonal - Math.sin(endAngle - Math.PI / 2) * gap2;
308
+ // SECOND ARC
319
309
 
310
+ let innerArcXTo = cx + Math.cos(startAngle + innerSmallArcAngle) * r0;
311
+ let innerArcYTo = cy - Math.sin(startAngle + innerSmallArcAngle) * r0;
312
+ // add large inner arc
320
313
  path.push(
321
- line(outerSmallArc1XFrom, outerSmallArc1YFrom),
322
- arc(outerBr, outerBr, 0, 0, 0, outerSmallArc1XTo, outerSmallArc1YTo),
323
- arc(
324
- r,
325
- r,
326
- 0,
327
- largeArcFlag(endAngle - outerSmallArcAngle - startAngle - outerSmallArcAngle),
328
- 0,
329
- outerLargeArcXTo,
330
- outerLargeArcYTo,
331
- ),
332
- arc(outerBr, outerBr, 0, 0, 0, outerSmallArc2XTo, outerSmallArc2YTo),
314
+ arc(
315
+ r0,
316
+ r0,
317
+ 0,
318
+ largeArcFlag(
319
+ endAngle - innerSmallArcAngle - startAngle - innerSmallArcAngle,
320
+ ),
321
+ 1,
322
+ innerArcXTo,
323
+ innerArcYTo,
324
+ ),
333
325
  );
334
- } else {
335
- if (r0 > 0) {
336
- let innerGapAngle = r0 > 0 && gap2 > 0 ? Math.asin(gap2 / r0) : 0;
337
- let innerStartAngle = startAngle + innerGapAngle;
338
- let innerEndAngle = endAngle - innerGapAngle;
339
- let startX = cx + Math.cos(innerEndAngle) * r0;
340
- let startY = cy - Math.sin(innerEndAngle) * r0;
341
- path.push(move(startX, startY));
342
-
343
- let innerArcToX = cx + Math.cos(innerStartAngle) * r0;
344
- let innerArcToY = cy - Math.sin(innerStartAngle) * r0;
345
-
346
- path.push(arc(r0, r0, 0, largeArcFlag(innerStartAngle - innerEndAngle), 1, innerArcToX, innerArcToY));
347
- } else {
348
- path.push(move(cx, cy));
349
- }
350
-
351
- let outerGapAngle = r > 0 && gap2 > 0 ? Math.asin(gap2 / r) : 0;
352
- let outerStartAngle = startAngle + outerGapAngle;
353
- let outerEndAngle = endAngle - outerGapAngle;
354
- let lineToX = cx + Math.cos(outerStartAngle) * r;
355
- let lineToY = cy - Math.sin(outerStartAngle) * r;
356
- path.push(line(lineToX, lineToY));
357
326
 
358
- let arcToX = cx + Math.cos(outerEndAngle) * r;
359
- let arcToY = cy - Math.sin(outerEndAngle) * r;
360
- path.push(arc(r, r, 0, largeArcFlag(outerEndAngle - outerStartAngle), 0, arcToX, arcToY));
361
- }
327
+ let innerSmallArc2XTo =
328
+ cx +
329
+ Math.cos(startAngle) * innerHipDiagonal +
330
+ Math.cos(startAngle + Math.PI / 2) * gap2;
331
+ let innerSmallArc2YTo =
332
+ cy -
333
+ Math.sin(startAngle) * innerHipDiagonal -
334
+ Math.sin(startAngle + Math.PI / 2) * gap2;
335
+ // add second small inner arc
336
+ path.push(
337
+ arc(innerBr, innerBr, 0, 0, 0, innerSmallArc2XTo, innerSmallArc2YTo),
338
+ );
339
+ } else {
340
+ path.push(move(cx, cy));
341
+ }
342
+
343
+ let outerBr = br;
344
+ let outerSmallArcAngle = Math.asin((br + gap2) / (r - br));
345
+
346
+ // tweak br according to the available area
347
+ if (outerSmallArcAngle > (endAngle - startAngle) / 2) {
348
+ outerSmallArcAngle = (endAngle - startAngle) / 2;
349
+ let sin = Math.sin(outerSmallArcAngle);
350
+ outerBr = Math.max((r * sin - gap2) / (1 + sin), 0);
351
+ }
352
+
353
+ let outerHipDiagonal = Math.cos(outerSmallArcAngle) * (r - outerBr);
354
+
355
+ let outerSmallArc1XFrom =
356
+ cx +
357
+ Math.cos(startAngle) * outerHipDiagonal +
358
+ Math.cos(startAngle + Math.PI / 2) * gap2;
359
+ let outerSmallArc1YFrom =
360
+ cy -
361
+ Math.sin(startAngle) * outerHipDiagonal -
362
+ Math.sin(startAngle + Math.PI / 2) * gap2;
363
+
364
+ let outerSmallArc1XTo = cx + Math.cos(startAngle + outerSmallArcAngle) * r;
365
+ let outerSmallArc1YTo = cy - Math.sin(startAngle + outerSmallArcAngle) * r;
366
+
367
+ let outerLargeArcXTo = cx + Math.cos(endAngle - outerSmallArcAngle) * r;
368
+ let outerLargeArcYTo = cy - Math.sin(endAngle - outerSmallArcAngle) * r;
369
+
370
+ let outerSmallArc2XTo =
371
+ cx +
372
+ Math.cos(endAngle) * outerHipDiagonal +
373
+ Math.cos(endAngle - Math.PI / 2) * gap2;
374
+ let outerSmallArc2YTo =
375
+ cy -
376
+ Math.sin(endAngle) * outerHipDiagonal -
377
+ Math.sin(endAngle - Math.PI / 2) * gap2;
378
+
379
+ path.push(
380
+ line(outerSmallArc1XFrom, outerSmallArc1YFrom),
381
+ arc(outerBr, outerBr, 0, 0, 0, outerSmallArc1XTo, outerSmallArc1YTo),
382
+ arc(
383
+ r,
384
+ r,
385
+ 0,
386
+ largeArcFlag(
387
+ endAngle - outerSmallArcAngle - startAngle - outerSmallArcAngle,
388
+ ),
389
+ 0,
390
+ outerLargeArcXTo,
391
+ outerLargeArcYTo,
392
+ ),
393
+ arc(outerBr, outerBr, 0, 0, 0, outerSmallArc2XTo, outerSmallArc2YTo),
394
+ );
395
+ } else {
396
+ if (r0 > 0) {
397
+ let innerGapAngle = r0 > 0 && gap2 > 0 ? Math.asin(gap2 / r0) : 0;
398
+ let innerStartAngle = startAngle + innerGapAngle;
399
+ let innerEndAngle = endAngle - innerGapAngle;
400
+ let startX = cx + Math.cos(innerEndAngle) * r0;
401
+ let startY = cy - Math.sin(innerEndAngle) * r0;
402
+ path.push(move(startX, startY));
403
+
404
+ let innerArcToX = cx + Math.cos(innerStartAngle) * r0;
405
+ let innerArcToY = cy - Math.sin(innerStartAngle) * r0;
362
406
 
363
- path.push(z());
364
- return path.join(" ");
407
+ path.push(
408
+ arc(
409
+ r0,
410
+ r0,
411
+ 0,
412
+ largeArcFlag(innerStartAngle - innerEndAngle),
413
+ 1,
414
+ innerArcToX,
415
+ innerArcToY,
416
+ ),
417
+ );
418
+ } else {
419
+ path.push(move(cx, cy));
420
+ }
421
+
422
+ let outerGapAngle = r > 0 && gap2 > 0 ? Math.asin(gap2 / r) : 0;
423
+ let outerStartAngle = startAngle + outerGapAngle;
424
+ let outerEndAngle = endAngle - outerGapAngle;
425
+ let lineToX = cx + Math.cos(outerStartAngle) * r;
426
+ let lineToY = cy - Math.sin(outerStartAngle) * r;
427
+ path.push(line(lineToX, lineToY));
428
+
429
+ let arcToX = cx + Math.cos(outerEndAngle) * r;
430
+ let arcToY = cy - Math.sin(outerEndAngle) * r;
431
+ path.push(
432
+ arc(
433
+ r,
434
+ r,
435
+ 0,
436
+ largeArcFlag(outerEndAngle - outerStartAngle),
437
+ 0,
438
+ arcToX,
439
+ arcToY,
440
+ ),
441
+ );
442
+ }
443
+
444
+ path.push(z());
445
+ return path.join(" ");
365
446
  }
366
447
 
367
448
  PieChart.prototype.anchors = "0 1 1 0";
@@ -370,334 +451,379 @@ PieChart.prototype.startAngle = 0;
370
451
  PieChart.prototype.gap = 0;
371
452
 
372
453
  export interface PieSliceConfig extends StyledContainerConfig {
373
- /** Used to indicate if a slice is active or not. Inactive slices are not rendered. */
374
- active?: BooleanProp;
454
+ /** Used to indicate if a slice is active or not. Inactive slices are not rendered. */
455
+ active?: BooleanProp;
375
456
 
376
- /** Inner radius of the slice. Default is `0`. */
377
- r0?: NumberProp;
457
+ /** Inner radius of the slice. Default is `0`. */
458
+ r0?: NumberProp;
378
459
 
379
- /** Outer radius of the slice. Default is `50`. */
380
- r?: NumberProp;
460
+ /** Outer radius of the slice. Default is `50`. */
461
+ r?: NumberProp;
381
462
 
382
- /** Index of a color from the standard palette of colors. 0-15. */
383
- colorIndex?: NumberProp;
463
+ /** Index of a color from the standard palette of colors. 0-15. */
464
+ colorIndex?: NumberProp;
384
465
 
385
- /** Used to automatically assign a color based on the `name` and the contextual `ColorMap` widget. */
386
- colorMap?: StringProp;
466
+ /** Used to automatically assign a color based on the `name` and the contextual `ColorMap` widget. */
467
+ colorMap?: StringProp;
387
468
 
388
- /** Name used to resolve the color. If not provided, `name` is used instead. */
389
- colorName?: StringProp;
469
+ /** Name used to resolve the color. If not provided, `name` is used instead. */
470
+ colorName?: StringProp;
390
471
 
391
- /** Offset of the slice from the center. */
392
- offset?: NumberProp;
472
+ /** Offset of the slice from the center. */
473
+ offset?: NumberProp;
393
474
 
394
- /** Value represented by the slice. */
395
- value?: NumberProp;
475
+ /** Value represented by the slice. */
476
+ value?: NumberProp;
396
477
 
397
- /** Set to `true` to disable the slice. */
398
- disabled?: BooleanProp;
478
+ /** Set to `true` to disable the slice. */
479
+ disabled?: BooleanProp;
399
480
 
400
- /** Inner radius for point calculations. */
401
- innerPointRadius?: NumberProp;
481
+ /** Inner radius for point calculations. */
482
+ innerPointRadius?: NumberProp;
402
483
 
403
- /** Outer radius for point calculations. */
404
- outerPointRadius?: NumberProp;
484
+ /** Outer radius for point calculations. */
485
+ outerPointRadius?: NumberProp;
405
486
 
406
- /** Name of the item as it will appear in the legend. */
407
- name?: StringProp;
487
+ /** Name of the item as it will appear in the legend. */
488
+ name?: StringProp;
408
489
 
409
- /** Stack name. Default is `stack`. */
410
- stack?: StringProp;
490
+ /** Stack name. Default is `stack`. */
491
+ stack?: StringProp;
411
492
 
412
- /** Name of the legend to be used. Default is `legend`. Set to `false` to hide the legend entry. */
413
- legend?: StringProp;
493
+ /** Name of the legend to be used. Default is `legend`. Set to `false` to hide the legend entry. */
494
+ legend?: Prop<string | false>;
414
495
 
415
- /** ID used for hover synchronization. */
416
- hoverId?: StringProp;
496
+ /** ID used for hover synchronization. */
497
+ hoverId?: StringProp | NumberProp;
417
498
 
418
- /** Border radius for rounded corners. */
419
- br?: NumberProp;
499
+ /** Border radius for rounded corners. */
500
+ br?: NumberProp;
420
501
 
421
- /** Alias for br (border radius). */
422
- borderRadius?: number;
502
+ /** Alias for br (border radius). */
503
+ borderRadius?: NumberProp;
423
504
 
424
- /** Text to display in the legend. */
425
- legendDisplayText?: StringProp;
505
+ /** Text to display in the legend. */
506
+ legendDisplayText?: StringProp;
426
507
 
427
- /** Set to `true` to use percentage-based radius. Default is `true`. */
428
- percentageRadius?: boolean;
508
+ /** Set to `true` to use percentage-based radius. Default is `true`. */
509
+ percentageRadius?: boolean;
429
510
 
430
- /** Shape to use in legend. Default is `circle`. */
431
- legendShape?: string;
511
+ /** Shape to use in legend. Default is `circle`. */
512
+ legendShape?: string;
432
513
 
433
- /** Action to perform on legend item click. Default is `auto`. */
434
- legendAction?: string;
514
+ /** Action to perform on legend item click. Default is `auto`. */
515
+ legendAction?: string;
435
516
 
436
- /** Hover channel for hover synchronization. Default is `default`. */
437
- hoverChannel?: string;
517
+ /** Hover channel for hover synchronization. Default is `default`. */
518
+ hoverChannel?: string;
438
519
 
439
- /** Selection configuration. */
440
- selection?: CreateConfig<typeof Selection> | CreateConfig<typeof KeySelection> | CreateConfig<typeof PropertySelection> | CreateConfig<typeof SimpleSelection>;
520
+ /** Selection configuration. */
521
+ selection?:
522
+ | CreateConfig<typeof Selection>
523
+ | CreateConfig<typeof KeySelection>
524
+ | CreateConfig<typeof PropertySelection>
525
+ | CreateConfig<typeof SimpleSelection>;
441
526
 
442
- /** Tooltip configuration. */
443
- tooltip?: any;
527
+ /** Tooltip configuration. */
528
+ tooltip?: any;
444
529
  }
445
530
 
446
531
  export interface PieSliceInstance extends Instance, TooltipParentInstance {
447
- pie: PieCalculator;
448
- valid: boolean;
449
- colorMap: any;
450
- hoverSync: any;
451
- segment: PieSegment;
452
- bounds: Rect;
532
+ pie: PieCalculator;
533
+ valid: boolean;
534
+ colorMap: any;
535
+ hoverSync: any;
536
+ segment: PieSegment;
537
+ bounds: Rect;
453
538
  }
454
539
 
455
540
  Widget.alias("pie-slice");
456
541
  export class PieSlice extends Container {
457
- declare baseClass: string;
458
- declare offset: number;
459
- declare r0: number;
460
- declare r: number;
461
- declare percentageRadius: boolean;
462
- declare legend: string;
463
- declare active: boolean;
464
- declare stack: string;
465
- declare legendAction: string;
466
- declare legendShape: string;
467
- declare hoverChannel: string;
468
- declare br: number;
469
- declare borderRadius: number;
470
- declare selection: Selection;
471
- declare tooltip: any;
472
-
473
- constructor(config: PieSliceConfig) {
474
- super(config);
475
- }
476
-
477
- init(): void {
478
- this.selection = Selection.create(this.selection);
479
- if (this.borderRadius) this.br = this.borderRadius;
480
- super.init();
481
- }
482
-
483
- declareData(...args: any[]): void {
484
- let selection = this.selection.configureWidget(this);
485
- super.declareData(...args, selection, {
486
- active: true,
487
- r0: undefined,
488
- r: undefined,
489
- colorIndex: undefined,
490
- colorMap: undefined,
491
- colorName: undefined,
492
- offset: undefined,
493
- value: undefined,
494
- disabled: undefined,
495
- innerPointRadius: undefined,
496
- outerPointRadius: undefined,
497
- name: undefined,
498
- stack: undefined,
499
- legend: undefined,
500
- hoverId: undefined,
501
- br: undefined,
502
- legendDisplayText: undefined,
503
- });
504
- }
505
-
506
- prepareData(context: RenderingContext, instance: PieSliceInstance): void {
507
- let { data } = instance;
508
-
509
- if (data.name && !data.colorName) data.colorName = data.name;
510
-
511
- super.prepareData(context, instance);
512
- }
513
-
514
- explore(context: RenderingContext, instance: PieSliceInstance): void {
515
- instance.pie = context.pie;
516
- if (!instance.pie) throw new Error("Pie.Slice must be placed inside a Pie.");
517
-
518
- let { data } = instance;
519
-
520
- instance.valid = isNumber(data.value) && data.value > 0;
521
-
522
- instance.colorMap = data.colorMap && context.getColorMap && context.getColorMap(data.colorMap);
523
- if (instance.colorMap && data.colorName) instance.colorMap.acknowledge(data.colorName);
524
-
525
- instance.hoverSync = context.hoverSync;
526
-
527
- if (instance.valid && data.active) {
528
- instance.pie.acknowledge(data.stack, data.value, data.r, data.r0, this.percentageRadius);
529
- super.explore(context, instance);
530
- }
531
- }
532
-
533
- prepare(context: RenderingContext, instance: PieSliceInstance): void {
534
- let { data, segment, pie, colorMap } = instance;
535
-
536
- if (colorMap && data.colorName) {
537
- data.colorIndex = colorMap.map(data.colorName);
538
- if (instance.cache("colorIndex", data.colorIndex)) instance.markShouldUpdate(context);
539
- }
542
+ declare baseClass: string;
543
+ declare offset: number;
544
+ declare r0: number;
545
+ declare r: number;
546
+ declare percentageRadius: boolean;
547
+ declare legend: string;
548
+ declare active: boolean;
549
+ declare stack: string;
550
+ declare legendAction: string;
551
+ declare legendShape: string;
552
+ declare hoverChannel: string;
553
+ declare br: number;
554
+ declare borderRadius: number;
555
+ declare selection: Selection;
556
+ declare tooltip: any;
557
+
558
+ constructor(config: PieSliceConfig) {
559
+ super(config);
560
+ }
561
+
562
+ init(): void {
563
+ this.selection = Selection.create(this.selection);
564
+ if (this.borderRadius) this.br = this.borderRadius;
565
+ super.init();
566
+ }
567
+
568
+ declareData(...args: any[]): void {
569
+ let selection = this.selection.configureWidget(this);
570
+ super.declareData(...args, selection, {
571
+ active: true,
572
+ r0: undefined,
573
+ r: undefined,
574
+ colorIndex: undefined,
575
+ colorMap: undefined,
576
+ colorName: undefined,
577
+ offset: undefined,
578
+ value: undefined,
579
+ disabled: undefined,
580
+ innerPointRadius: undefined,
581
+ outerPointRadius: undefined,
582
+ name: undefined,
583
+ stack: undefined,
584
+ legend: undefined,
585
+ hoverId: undefined,
586
+ br: undefined,
587
+ legendDisplayText: undefined,
588
+ });
589
+ }
590
+
591
+ prepareData(context: RenderingContext, instance: PieSliceInstance): void {
592
+ let { data } = instance;
593
+
594
+ if (data.name && !data.colorName) data.colorName = data.name;
595
+
596
+ super.prepareData(context, instance);
597
+ }
598
+
599
+ explore(context: RenderingContext, instance: PieSliceInstance): void {
600
+ instance.pie = context.pie;
601
+ if (!instance.pie)
602
+ throw new Error("Pie.Slice must be placed inside a Pie.");
603
+
604
+ let { data } = instance;
605
+
606
+ instance.valid = isNumber(data.value) && data.value > 0;
607
+
608
+ instance.colorMap =
609
+ data.colorMap &&
610
+ context.getColorMap &&
611
+ context.getColorMap(data.colorMap);
612
+ if (instance.colorMap && data.colorName)
613
+ instance.colorMap.acknowledge(data.colorName);
614
+
615
+ instance.hoverSync = context.hoverSync;
616
+
617
+ if (instance.valid && data.active) {
618
+ instance.pie.acknowledge(
619
+ data.stack,
620
+ data.value,
621
+ data.r,
622
+ data.r0,
623
+ this.percentageRadius,
624
+ );
625
+ super.explore(context, instance);
626
+ }
627
+ }
628
+
629
+ prepare(context: RenderingContext, instance: PieSliceInstance): void {
630
+ let { data, segment, pie, colorMap } = instance;
631
+
632
+ if (colorMap && data.colorName) {
633
+ data.colorIndex = colorMap.map(data.colorName);
634
+ if (instance.cache("colorIndex", data.colorIndex))
635
+ instance.markShouldUpdate(context);
636
+ }
637
+
638
+ if (instance.valid && data.active) {
639
+ let seg = pie.map(
640
+ data.stack,
641
+ data.value,
642
+ data.r,
643
+ data.r0,
644
+ this.percentageRadius,
645
+ );
540
646
 
541
- if (instance.valid && data.active) {
542
- let seg = pie.map(data.stack, data.value, data.r, data.r0, this.percentageRadius);
543
-
544
- if (
545
- !segment ||
546
- instance.shouldUpdate ||
547
- seg.startAngle != segment.startAngle ||
548
- seg.endAngle != segment.endAngle ||
549
- pie.shouldUpdate
550
- ) {
551
- if (data.offset > 0) {
552
- seg.ox = seg.cx + Math.cos(seg.midAngle) * data.offset;
553
- seg.oy = seg.cy - Math.sin(seg.midAngle) * data.offset;
554
- } else {
555
- seg.ox = seg.cx;
556
- seg.oy = seg.cy;
557
- }
558
-
559
- seg.radiusMultiplier = 1;
560
- if (this.percentageRadius) seg.radiusMultiplier = seg.R / 100;
561
-
562
- let innerR = data.innerPointRadius != null ? data.innerPointRadius : data.r0;
563
- let outerR = data.outerPointRadius != null ? data.outerPointRadius : data.r;
564
-
565
- let ix = seg.ox! + Math.cos(seg.midAngle) * innerR * seg.radiusMultiplier;
566
- let iy = seg.oy! - Math.sin(seg.midAngle) * innerR * seg.radiusMultiplier;
567
- let ox = seg.ox! + Math.cos(seg.midAngle) * outerR * seg.radiusMultiplier;
568
- let oy = seg.oy! - Math.sin(seg.midAngle) * outerR * seg.radiusMultiplier;
569
-
570
- instance.segment = seg;
571
- instance.bounds = new Rect({
572
- l: ix,
573
- r: ox,
574
- t: iy,
575
- b: oy,
576
- });
577
-
578
- instance.markShouldUpdate(context);
579
- }
580
-
581
- context.push("parentRect", instance.bounds);
647
+ if (
648
+ !segment ||
649
+ instance.shouldUpdate ||
650
+ seg.startAngle != segment.startAngle ||
651
+ seg.endAngle != segment.endAngle ||
652
+ pie.shouldUpdate
653
+ ) {
654
+ if (data.offset > 0) {
655
+ seg.ox = seg.cx + Math.cos(seg.midAngle) * data.offset;
656
+ seg.oy = seg.cy - Math.sin(seg.midAngle) * data.offset;
657
+ } else {
658
+ seg.ox = seg.cx;
659
+ seg.oy = seg.cy;
660
+ }
661
+
662
+ seg.radiusMultiplier = 1;
663
+ if (this.percentageRadius) seg.radiusMultiplier = seg.R / 100;
664
+
665
+ let innerR =
666
+ data.innerPointRadius != null ? data.innerPointRadius : data.r0;
667
+ let outerR =
668
+ data.outerPointRadius != null ? data.outerPointRadius : data.r;
669
+
670
+ let ix =
671
+ seg.ox! + Math.cos(seg.midAngle) * innerR * seg.radiusMultiplier;
672
+ let iy =
673
+ seg.oy! - Math.sin(seg.midAngle) * innerR * seg.radiusMultiplier;
674
+ let ox =
675
+ seg.ox! + Math.cos(seg.midAngle) * outerR * seg.radiusMultiplier;
676
+ let oy =
677
+ seg.oy! - Math.sin(seg.midAngle) * outerR * seg.radiusMultiplier;
678
+
679
+ instance.segment = seg;
680
+ instance.bounds = new Rect({
681
+ l: ix,
682
+ r: ox,
683
+ t: iy,
684
+ b: oy,
685
+ });
686
+
687
+ instance.markShouldUpdate(context);
582
688
  }
583
689
 
584
- if (data.name && data.legend && context.addLegendEntry)
585
- context.addLegendEntry(data.legend, {
586
- name: data.name,
587
- active: data.active,
588
- colorIndex: data.colorIndex,
589
- disabled: data.disabled,
590
- selected: this.selection.isInstanceSelected(instance),
591
- style: data.style,
592
- shape: this.legendShape,
593
- hoverId: data.hoverId,
594
- hoverChannel: this.hoverChannel,
595
- hoverSync: instance.hoverSync,
596
- displayText: data.legendDisplayText,
597
- value: data.value,
598
- onClick: (e: MouseEvent) => {
599
- this.onLegendClick(e, instance);
600
- },
601
- });
602
- }
603
-
604
- prepareCleanup(context: RenderingContext, instance: PieSliceInstance): void {
605
- if (instance.valid && instance.data.active) {
606
- context.pop("parentRect");
607
- }
608
- }
609
-
610
- onLegendClick(e: MouseEvent | React.MouseEvent, instance: PieSliceInstance): void {
611
- let allActions = this.legendAction == "auto";
612
- let { data } = instance;
613
- if (allActions || this.legendAction == "toggle") if (instance.set("active", !data.active)) return;
614
-
615
- if (allActions || this.legendAction == "select") this.handleClick(e as React.MouseEvent, instance);
616
- }
617
-
618
- render(context: RenderingContext, instance: PieSliceInstance, key: string): React.ReactNode {
619
- let { segment, data } = instance;
620
- if (!instance.valid || !data.active) return null;
621
-
622
- return withHoverSync(
623
- key,
624
- instance.hoverSync,
625
- this.hoverChannel,
626
- data.hoverId,
627
- ({ hover, onMouseMove, onMouseLeave }) => {
628
- let stateMods: Record<string, any> = {
629
- selected: this.selection.isInstanceSelected(instance),
630
- disabled: data.disabled,
631
- selectable: !this.selection.isDummy,
632
- [`color-${data.colorIndex}`]: data.colorIndex != null,
633
- hover,
634
- };
635
-
636
- let d = createSvgArc(
637
- segment.ox!,
638
- segment.oy!,
639
- data.r0 * segment.radiusMultiplier!,
640
- data.r * segment.radiusMultiplier!,
641
- segment.startAngle,
642
- segment.endAngle,
643
- data.br,
644
- segment.gap,
645
- );
646
-
647
- return (
648
- <g key={key} className={data.classNames}>
649
- <path
650
- className={this.CSS.element(this.baseClass, "slice", stateMods)}
651
- style={data.style}
652
- d={d}
653
- onMouseMove={(e) => {
654
- onMouseMove(e, instance);
655
- tooltipMouseMove(e, instance, this.tooltip);
656
- }}
657
- onMouseLeave={(e) => {
658
- onMouseLeave(e, instance);
659
- tooltipMouseLeave(e, instance, this.tooltip);
660
- }}
661
- onClick={(e) => {
662
- this.handleClick(e, instance);
663
- }}
664
- />
665
- {this.renderChildren(context, instance)}
666
- </g>
667
- );
668
- },
669
- );
670
- }
671
-
672
- handleClick(e: React.MouseEvent, instance: PieSliceInstance): void {
673
- if (!this.selection.isDummy) {
674
- this.selection.selectInstance(instance, {
675
- toggle: e.ctrlKey,
676
- });
677
- e.stopPropagation();
678
- e.preventDefault();
679
- }
680
- }
690
+ context.push("parentRect", instance.bounds);
691
+ }
692
+
693
+ if (data.name && data.legend && context.addLegendEntry)
694
+ context.addLegendEntry(data.legend, {
695
+ name: data.name,
696
+ active: data.active,
697
+ colorIndex: data.colorIndex,
698
+ disabled: data.disabled,
699
+ selected: this.selection.isInstanceSelected(instance),
700
+ style: data.style,
701
+ shape: this.legendShape,
702
+ hoverId: data.hoverId,
703
+ hoverChannel: this.hoverChannel,
704
+ hoverSync: instance.hoverSync,
705
+ displayText: data.legendDisplayText,
706
+ value: data.value,
707
+ onClick: (e: MouseEvent) => {
708
+ this.onLegendClick(e, instance);
709
+ },
710
+ });
711
+ }
712
+
713
+ prepareCleanup(context: RenderingContext, instance: PieSliceInstance): void {
714
+ if (instance.valid && instance.data.active) {
715
+ context.pop("parentRect");
716
+ }
717
+ }
718
+
719
+ onLegendClick(
720
+ e: MouseEvent | React.MouseEvent,
721
+ instance: PieSliceInstance,
722
+ ): void {
723
+ let allActions = this.legendAction == "auto";
724
+ let { data } = instance;
725
+ if (allActions || this.legendAction == "toggle")
726
+ if (instance.set("active", !data.active)) return;
727
+
728
+ if (allActions || this.legendAction == "select")
729
+ this.handleClick(e as React.MouseEvent, instance);
730
+ }
731
+
732
+ render(
733
+ context: RenderingContext,
734
+ instance: PieSliceInstance,
735
+ key: string,
736
+ ): React.ReactNode {
737
+ let { segment, data } = instance;
738
+ if (!instance.valid || !data.active) return null;
739
+
740
+ return withHoverSync(
741
+ key,
742
+ instance.hoverSync,
743
+ this.hoverChannel,
744
+ data.hoverId,
745
+ ({ hover, onMouseMove, onMouseLeave }) => {
746
+ let stateMods: Record<string, any> = {
747
+ selected: this.selection.isInstanceSelected(instance),
748
+ disabled: data.disabled,
749
+ selectable: !this.selection.isDummy,
750
+ [`color-${data.colorIndex}`]: data.colorIndex != null,
751
+ hover,
752
+ };
753
+
754
+ let d = createSvgArc(
755
+ segment.ox!,
756
+ segment.oy!,
757
+ data.r0 * segment.radiusMultiplier!,
758
+ data.r * segment.radiusMultiplier!,
759
+ segment.startAngle,
760
+ segment.endAngle,
761
+ data.br,
762
+ segment.gap,
763
+ );
764
+
765
+ return (
766
+ <g key={key} className={data.classNames}>
767
+ <path
768
+ className={this.CSS.element(this.baseClass, "slice", stateMods)}
769
+ style={data.style}
770
+ d={d}
771
+ onMouseMove={(e) => {
772
+ onMouseMove(e, instance);
773
+ tooltipMouseMove(e, instance, this.tooltip);
774
+ }}
775
+ onMouseLeave={(e) => {
776
+ onMouseLeave(e, instance);
777
+ tooltipMouseLeave(e, instance, this.tooltip);
778
+ }}
779
+ onClick={(e) => {
780
+ this.handleClick(e, instance);
781
+ }}
782
+ />
783
+ {this.renderChildren(context, instance)}
784
+ </g>
785
+ );
786
+ },
787
+ );
788
+ }
789
+
790
+ handleClick(e: React.MouseEvent, instance: PieSliceInstance): void {
791
+ if (!this.selection.isDummy) {
792
+ this.selection.selectInstance(instance, {
793
+ toggle: e.ctrlKey,
794
+ });
795
+ e.stopPropagation();
796
+ e.preventDefault();
797
+ }
798
+ }
681
799
  }
682
800
 
683
801
  function move(x: number, y: number): string {
684
- return `M ${x} ${y}`;
802
+ return `M ${x} ${y}`;
685
803
  }
686
804
 
687
805
  function line(x: number, y: number): string {
688
- return `L ${x} ${y}`;
806
+ return `L ${x} ${y}`;
689
807
  }
690
808
 
691
809
  function z(): string {
692
- return "Z";
810
+ return "Z";
693
811
  }
694
812
 
695
- function arc(rx: number, ry: number, xRotation: number, largeArc: number, sweep: number, x: number, y: number): string {
696
- return `A ${rx} ${ry} ${xRotation} ${largeArc} ${sweep} ${x} ${y}`;
813
+ function arc(
814
+ rx: number,
815
+ ry: number,
816
+ xRotation: number,
817
+ largeArc: number,
818
+ sweep: number,
819
+ x: number,
820
+ y: number,
821
+ ): string {
822
+ return `A ${rx} ${ry} ${xRotation} ${largeArc} ${sweep} ${x} ${y}`;
697
823
  }
698
824
 
699
825
  function largeArcFlag(angle: number): number {
700
- return angle > Math.PI || angle < -Math.PI ? 1 : 0;
826
+ return angle > Math.PI || angle < -Math.PI ? 1 : 0;
701
827
  }
702
828
 
703
829
  PieSlice.prototype.offset = 0;