@pie-lib/charting 5.15.6 → 5.15.7-next.1618

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 (109) hide show
  1. package/CHANGELOG.json +1 -581
  2. package/CHANGELOG.md +206 -38
  3. package/NEXT.CHANGELOG.json +1 -0
  4. package/lib/actions-button.js +175 -0
  5. package/lib/actions-button.js.map +1 -0
  6. package/lib/axes.js +154 -104
  7. package/lib/axes.js.map +1 -1
  8. package/lib/bars/common/bars.js +105 -19
  9. package/lib/bars/common/bars.js.map +1 -1
  10. package/lib/bars/common/correct-check-icon.js +55 -0
  11. package/lib/bars/common/correct-check-icon.js.map +1 -0
  12. package/lib/chart-type.js +4 -4
  13. package/lib/chart-type.js.map +1 -1
  14. package/lib/chart.js +96 -65
  15. package/lib/chart.js.map +1 -1
  16. package/lib/common/correctness-indicators.js +99 -0
  17. package/lib/common/correctness-indicators.js.map +1 -0
  18. package/lib/common/drag-handle.js +47 -13
  19. package/lib/common/drag-handle.js.map +1 -1
  20. package/lib/common/drag-icon.js +7 -24
  21. package/lib/common/drag-icon.js.map +1 -1
  22. package/lib/grid.js +47 -10
  23. package/lib/grid.js.map +1 -1
  24. package/lib/index.js +8 -0
  25. package/lib/index.js.map +1 -1
  26. package/lib/key-legend.js +111 -0
  27. package/lib/key-legend.js.map +1 -0
  28. package/lib/line/common/drag-handle.js +40 -18
  29. package/lib/line/common/drag-handle.js.map +1 -1
  30. package/lib/line/common/line.js +7 -8
  31. package/lib/line/common/line.js.map +1 -1
  32. package/lib/line/line-cross.js +76 -9
  33. package/lib/line/line-cross.js.map +1 -1
  34. package/lib/line/line-dot.js +58 -5
  35. package/lib/line/line-dot.js.map +1 -1
  36. package/lib/mark-label.js +40 -15
  37. package/lib/mark-label.js.map +1 -1
  38. package/lib/plot/common/plot.js +129 -16
  39. package/lib/plot/common/plot.js.map +1 -1
  40. package/lib/plot/dot.js +17 -4
  41. package/lib/plot/dot.js.map +1 -1
  42. package/lib/plot/line.js +19 -6
  43. package/lib/plot/line.js.map +1 -1
  44. package/lib/tool-menu.js +0 -4
  45. package/lib/tool-menu.js.map +1 -1
  46. package/package.json +6 -8
  47. package/src/__tests__/__snapshots__/axes.test.jsx.snap +569 -0
  48. package/src/__tests__/__snapshots__/chart-type.test.jsx.snap +14 -0
  49. package/src/__tests__/__snapshots__/chart.test.jsx.snap +595 -0
  50. package/src/__tests__/__snapshots__/grid.test.jsx.snap +72 -0
  51. package/src/__tests__/__snapshots__/mark-label.test.jsx.snap +73 -0
  52. package/src/__tests__/axes.test.jsx +141 -0
  53. package/src/__tests__/chart-setup.test.jsx +47 -0
  54. package/src/__tests__/chart-type.test.jsx +29 -0
  55. package/src/__tests__/chart.test.jsx +95 -0
  56. package/src/__tests__/grid.test.jsx +25 -0
  57. package/src/__tests__/mark-label.test.jsx +31 -0
  58. package/src/__tests__/utils.js +30 -0
  59. package/src/__tests__/utils.test.js +100 -0
  60. package/src/actions-button.jsx +110 -0
  61. package/src/axes.jsx +98 -54
  62. package/src/bars/__tests__/__snapshots__/bar.test.jsx.snap +43 -0
  63. package/src/bars/__tests__/__snapshots__/histogram.test.jsx.snap +45 -0
  64. package/src/bars/__tests__/bar.test.jsx +37 -0
  65. package/src/bars/__tests__/histogram.test.jsx +38 -0
  66. package/src/bars/__tests__/utils.js +30 -0
  67. package/src/bars/common/__tests__/__snapshots__/bars.test.jsx.snap +110 -0
  68. package/src/bars/common/__tests__/bars.test.jsx +69 -0
  69. package/src/bars/common/__tests__/utils.js +30 -0
  70. package/src/bars/common/bars.jsx +101 -14
  71. package/src/bars/common/correct-check-icon.jsx +20 -0
  72. package/src/chart-type.js +7 -3
  73. package/src/chart.jsx +53 -29
  74. package/src/common/__tests__/__snapshots__/drag-handle.test.jsx.snap +48 -0
  75. package/src/common/__tests__/drag-handle.test.jsx +88 -0
  76. package/src/common/__tests__/utils.js +30 -0
  77. package/src/common/correctness-indicators.jsx +55 -0
  78. package/src/common/drag-handle.jsx +48 -26
  79. package/src/common/drag-icon.jsx +6 -21
  80. package/src/grid.jsx +37 -12
  81. package/src/index.js +2 -1
  82. package/src/key-legend.jsx +75 -0
  83. package/src/line/__tests__/__snapshots__/line-cross.test.jsx.snap +45 -0
  84. package/src/line/__tests__/__snapshots__/line-dot.test.jsx.snap +45 -0
  85. package/src/line/__tests__/line-cross.test.jsx +38 -0
  86. package/src/line/__tests__/line-dot.test.jsx +38 -0
  87. package/src/line/__tests__/utils.js +30 -0
  88. package/src/line/common/__tests__/__snapshots__/drag-handle.test.jsx.snap +49 -0
  89. package/src/line/common/__tests__/__snapshots__/line.test.jsx.snap +143 -0
  90. package/src/line/common/__tests__/drag-handle.test.jsx +88 -0
  91. package/src/line/common/__tests__/line.test.jsx +82 -0
  92. package/src/line/common/__tests__/utils.js +30 -0
  93. package/src/line/common/drag-handle.jsx +38 -16
  94. package/src/line/common/line.jsx +4 -6
  95. package/src/line/line-cross.js +56 -4
  96. package/src/line/line-dot.js +74 -10
  97. package/src/mark-label.jsx +83 -51
  98. package/src/plot/__tests__/__snapshots__/dot.test.jsx.snap +45 -0
  99. package/src/plot/__tests__/__snapshots__/line.test.jsx.snap +45 -0
  100. package/src/plot/__tests__/dot.test.jsx +38 -0
  101. package/src/plot/__tests__/line.test.jsx +38 -0
  102. package/src/plot/__tests__/utils.js +30 -0
  103. package/src/plot/common/__tests__/__snapshots__/plot.test.jsx.snap +97 -0
  104. package/src/plot/common/__tests__/plot.test.jsx +70 -0
  105. package/src/plot/common/__tests__/utils.js +30 -0
  106. package/src/plot/common/plot.jsx +127 -10
  107. package/src/plot/dot.js +19 -3
  108. package/src/plot/line.js +18 -4
  109. package/src/tool-menu.jsx +0 -4
@@ -0,0 +1,30 @@
1
+ export const scaleMock = () => {
2
+ const fn = jest.fn((n) => n);
3
+ fn.invert = jest.fn((n) => n);
4
+ return fn;
5
+ };
6
+
7
+ export const graphProps = (dmin = 0, dmax = 1, rmin = 0, rmax = 1) => ({
8
+ scale: {
9
+ x: scaleMock(),
10
+ y: scaleMock(),
11
+ },
12
+ snap: {
13
+ x: jest.fn((n) => n),
14
+ y: jest.fn((n) => n),
15
+ },
16
+ domain: {
17
+ min: dmin,
18
+ max: dmax,
19
+ step: 1,
20
+ },
21
+ range: {
22
+ min: rmin,
23
+ max: rmax,
24
+ step: 1,
25
+ },
26
+ size: {
27
+ width: 400,
28
+ height: 400,
29
+ },
30
+ });
@@ -1,13 +1,15 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { types } from '@pie-lib/plot';
4
3
  import { Group } from '@vx/group';
5
- import { color } from '@pie-lib/render-ui';
6
4
  import { Bar as VxBar } from '@vx/shape';
7
5
  import { withStyles } from '@material-ui/core/styles/index';
8
6
  import debug from 'debug';
7
+
8
+ import { color } from '@pie-lib/render-ui';
9
+ import { types } from '@pie-lib/plot';
9
10
  import { bandKey } from '../../utils';
10
11
  import DraggableHandle, { DragHandle } from '../../common/drag-handle';
12
+ import { CorrectCheckIcon } from './correct-check-icon';
11
13
 
12
14
  const log = debug('pie-lib:chart:bars');
13
15
  const histogramColors = [
@@ -39,12 +41,12 @@ const hoverHistogramColors = [
39
41
  '#894A65',
40
42
  ];
41
43
 
42
- const calculateFillColor = (isHovered, barColor, index, hoverHistogramColors) => {
43
- if (isHovered && barColor) {
44
+ const calculateFillColor = (isHovered, barColor, index, hoverHistogramColors, allowRolloverEvent) => {
45
+ if (isHovered && barColor && allowRolloverEvent) {
44
46
  return hoverHistogramColors[index % hoverHistogramColors.length];
45
47
  }
46
- if (isHovered) {
47
- return color.primaryDark();
48
+ if (isHovered && allowRolloverEvent) {
49
+ return color.visualElementsColors.ROLLOVER_FILL_BAR_COLOR;
48
50
  }
49
51
  return barColor || null;
50
52
  };
@@ -64,6 +66,7 @@ export class RawBar extends React.Component {
64
66
  value: PropTypes.string,
65
67
  label: PropTypes.string,
66
68
  }),
69
+ correctData: PropTypes.array,
67
70
  };
68
71
 
69
72
  constructor(props) {
@@ -72,8 +75,38 @@ export class RawBar extends React.Component {
72
75
  dragValue: undefined,
73
76
  isHovered: false,
74
77
  };
78
+ this.mouseX = 0;
79
+ this.mouseY = 0;
80
+ }
81
+
82
+ componentDidMount() {
83
+ window.addEventListener('mousemove', this.handleMouseMove);
84
+ }
85
+
86
+ componentWillUnmount() {
87
+ window.removeEventListener('mousemove', this.handleMouseMove);
75
88
  }
76
89
 
90
+ handleMouseMove = (e) => {
91
+ // Update mouse position
92
+ this.mouseX = e.clientX;
93
+ this.mouseY = e.clientY;
94
+ // Check if the mouse is inside the <g> element
95
+ const isMouseInside = this.isMouseInsideSvgElement();
96
+ this.setState({ isHovered: isMouseInside });
97
+ };
98
+
99
+ isMouseInsideSvgElement = () => {
100
+ const gBoundingBox = this.gRef.getBoundingClientRect();
101
+ // Check if the mouse position is within the bounding box
102
+ return (
103
+ this.mouseX >= gBoundingBox.left &&
104
+ this.mouseX <= gBoundingBox.right &&
105
+ this.mouseY >= gBoundingBox.top &&
106
+ this.mouseY <= gBoundingBox.bottom
107
+ );
108
+ };
109
+
77
110
  handleMouseEnter = () => {
78
111
  this.setState({ isHovered: true });
79
112
  };
@@ -114,23 +147,33 @@ export class RawBar extends React.Component {
114
147
  correctness,
115
148
  barColor,
116
149
  defineChart,
150
+ correctData,
117
151
  } = this.props;
118
152
  const { scale, range } = graphProps;
119
153
  const { dragValue, isHovered } = this.state;
120
154
 
121
- const fillColor = calculateFillColor(isHovered, barColor, index, hoverHistogramColors);
155
+ const allowRolloverEvent = interactive && !correctness;
156
+ const fillColor = calculateFillColor(isHovered, barColor, index, hoverHistogramColors, allowRolloverEvent);
122
157
  const v = Number.isFinite(dragValue) ? dragValue : value;
123
158
  const barWidth = xBand.bandwidth();
124
159
  const barHeight = scale.y(range.max - v);
125
160
  const barX = xBand(bandKey({ label }, index));
126
161
  const rawY = range.max - v;
127
162
  const yy = range.max - rawY;
163
+ const correctValue = correctData ? correctData.find((d) => d.label === label) : null;
128
164
  log('label:', label, 'barX:', barX, 'v: ', v, 'barHeight:', barHeight, 'barWidth: ', barWidth);
129
165
 
130
166
  const Component = interactive ? DraggableHandle : DragHandle;
167
+ const isHistogram = !!barColor;
131
168
 
132
169
  return (
133
- <g onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
170
+ <g
171
+ ref={(ref) => (this.gRef = ref)}
172
+ onMouseEnter={this.handleMouseEnter}
173
+ onMouseLeave={this.handleMouseLeave}
174
+ onTouchStart={this.handleMouseEnter}
175
+ onTouchEnd={this.handleMouseLeave}
176
+ >
134
177
  <VxBar
135
178
  x={barX}
136
179
  y={scale.y(yy)}
@@ -139,6 +182,40 @@ export class RawBar extends React.Component {
139
182
  className={classes.bar}
140
183
  style={{ fill: fillColor }}
141
184
  />
185
+ {correctness &&
186
+ correctness.value === 'incorrect' &&
187
+ (() => {
188
+ const correctVal = parseFloat(correctValue && correctValue.value);
189
+ if (isNaN(correctVal)) return null;
190
+ const correctPxHeight = scale.y(range.max - correctVal);
191
+ const actualPxHeight = barHeight;
192
+ const diffPx = Math.abs(correctPxHeight - actualPxHeight);
193
+ const yDiff = scale.y(correctVal);
194
+ const indicatorBarColor = correctPxHeight > actualPxHeight ? color.borderGray() : color.defaults.WHITE;
195
+ const yToRender = correctPxHeight > actualPxHeight ? yDiff : yDiff - diffPx;
196
+
197
+ return (
198
+ <>
199
+ <VxBar
200
+ x={barX + 2} // add 2px for the stroke (the dashed border)
201
+ y={yToRender}
202
+ width={barWidth - 4} // substract 4px for the total stroke
203
+ height={diffPx}
204
+ className={classes.bar}
205
+ style={{
206
+ stroke: indicatorBarColor,
207
+ strokeWidth: 2,
208
+ strokeDasharray: '5,2',
209
+ fill: 'none',
210
+ }}
211
+ />
212
+ {/* adjust the position based on whether it's a histogram or not, because the histogram does not have space for the icon on the side */}
213
+ <foreignObject x={barX + barWidth - (isHistogram ? 24 : 14)} y={yDiff - 12} width={24} height={24}>
214
+ <CorrectCheckIcon dashColor={indicatorBarColor} />
215
+ </foreignObject>
216
+ </>
217
+ );
218
+ })()}
142
219
  <Component
143
220
  x={barX}
144
221
  y={v}
@@ -157,18 +234,27 @@ export class RawBar extends React.Component {
157
234
  }
158
235
  }
159
236
 
160
- const Bar = withStyles(() => ({
237
+ const Bar = withStyles((theme) => ({
161
238
  bar: {
162
- fill: color.primaryLight(),
163
- '&:hover': {
164
- fill: color.primaryDark(),
165
- },
239
+ fill: color.defaults.TERTIARY,
240
+ },
241
+ correctIcon: {
242
+ backgroundColor: color.correct(),
243
+ borderRadius: theme.spacing.unit * 2,
244
+ color: color.defaults.WHITE,
245
+ fontSize: '10px',
246
+ width: '10px',
247
+ height: '10px',
248
+ padding: '2px',
249
+ border: `1px solid ${color.defaults.WHITE}`,
250
+ boxSizing: 'unset', // to override the default border-box in IBX
166
251
  },
167
252
  }))(RawBar);
168
253
 
169
254
  export class Bars extends React.Component {
170
255
  static propTypes = {
171
256
  data: PropTypes.array,
257
+ correctData: PropTypes.array,
172
258
  onChangeCategory: PropTypes.func,
173
259
  defineChart: PropTypes.bool,
174
260
  xBand: PropTypes.func,
@@ -177,7 +263,7 @@ export class Bars extends React.Component {
177
263
  };
178
264
 
179
265
  render() {
180
- const { data, graphProps, xBand, onChangeCategory, defineChart, histogram } = this.props;
266
+ const { data, graphProps, xBand, onChangeCategory, defineChart, histogram, correctData } = this.props;
181
267
 
182
268
  return (
183
269
  <Group>
@@ -193,6 +279,7 @@ export class Bars extends React.Component {
193
279
  onChangeCategory={(category) => onChangeCategory(index, category)}
194
280
  graphProps={graphProps}
195
281
  correctness={d.correctness}
282
+ correctData={correctData}
196
283
  barColor={
197
284
  histogram &&
198
285
  (histogramColors[index] ? histogramColors[index] : histogramColors[index % histogramColors.length])
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+
3
+ export const CorrectCheckIcon = ({ dashColor }) => (
4
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
5
+ <circle cx="12" cy="12" r="11" fill="white" stroke={dashColor || '#7E8494'} strokeWidth="2" strokeDasharray="5 5" />
6
+ <mask id="path-2-outside-1_3089_3799" maskUnits="userSpaceOnUse" x="2" y="3" width="19" height="18" fill="black">
7
+ <rect fill="white" x="2" y="3" width="19" height="18" />
8
+ <path d="M12 20C9.125 20 6.5 18.5 5.0625 16C3.625 13.5312 3.625 10.5 5.0625 8C6.5 5.53125 9.125 4 12 4C14.8438 4 17.4688 5.53125 18.9062 8C20.3438 10.5 20.3438 13.5312 18.9062 16C17.4688 18.5 14.8438 20 12 20ZM15.5312 10.5312H15.5C15.8125 10.25 15.8125 9.78125 15.5 9.46875C15.2188 9.1875 14.75 9.1875 14.4688 9.46875L11 12.9688L9.53125 11.5C9.21875 11.1875 8.75 11.1875 8.46875 11.5C8.15625 11.7812 8.15625 12.25 8.46875 12.5312L10.4688 14.5312C10.75 14.8438 11.2188 14.8438 11.5312 14.5312L15.5312 10.5312Z" />
9
+ </mask>
10
+ <path
11
+ d="M12 20C9.125 20 6.5 18.5 5.0625 16C3.625 13.5312 3.625 10.5 5.0625 8C6.5 5.53125 9.125 4 12 4C14.8438 4 17.4688 5.53125 18.9062 8C20.3438 10.5 20.3438 13.5312 18.9062 16C17.4688 18.5 14.8438 20 12 20ZM15.5312 10.5312H15.5C15.8125 10.25 15.8125 9.78125 15.5 9.46875C15.2188 9.1875 14.75 9.1875 14.4688 9.46875L11 12.9688L9.53125 11.5C9.21875 11.1875 8.75 11.1875 8.46875 11.5C8.15625 11.7812 8.15625 12.25 8.46875 12.5312L10.4688 14.5312C10.75 14.8438 11.2188 14.8438 11.5312 14.5312L15.5312 10.5312Z"
12
+ fill="#0EA449"
13
+ />
14
+ <path
15
+ d="M5.0625 16L5.92942 15.5015L5.92668 15.4968L5.0625 16ZM5.0625 8L4.19831 7.4968L4.19559 7.50153L5.0625 8ZM18.9062 8L19.7732 7.50152L19.7704 7.49681L18.9062 8ZM18.9062 16L18.0421 15.4968L18.0393 15.5015L18.9062 16ZM15.5312 10.5312L16.2384 11.2384L17.9455 9.53125H15.5312V10.5312ZM15.5 10.5312L14.831 9.78796L12.894 11.5312H15.5V10.5312ZM14.4688 9.46875L13.7616 8.76164L13.7585 8.76482L14.4688 9.46875ZM11 12.9688L10.2929 13.6759L11.0032 14.3861L11.7103 13.6727L11 12.9688ZM8.46875 11.5L9.13771 12.2433L9.17684 12.2081L9.21204 12.169L8.46875 11.5ZM8.46875 12.5312L9.17586 11.8241L9.15726 11.8055L9.13771 11.788L8.46875 12.5312ZM10.4688 14.5312L11.212 13.8623L11.1945 13.8427L11.1759 13.8241L10.4688 14.5312ZM12 20V19C9.479 19 7.18657 17.6879 5.92941 15.5015L5.0625 16L4.19559 16.4985C5.81343 19.3121 8.771 21 12 21V20ZM5.0625 16L5.92668 15.4968C4.6714 13.341 4.66824 10.6918 5.92941 8.49847L5.0625 8L4.19559 7.50153C2.58176 10.3082 2.5786 13.7215 4.19832 16.5032L5.0625 16ZM5.0625 8L5.92668 8.50319C7.18712 6.33851 9.48502 5 12 5V4V3C8.76498 3 5.81288 4.72399 4.19832 7.49681L5.0625 8ZM12 4V5C14.4816 5 16.7805 6.33661 18.0421 8.50319L18.9062 8L19.7704 7.49681C18.157 4.72589 15.2059 3 12 3V4ZM18.9062 8L18.0393 8.49847C19.3005 10.6918 19.2973 13.341 18.0421 15.4968L18.9062 16L19.7704 16.5032C21.3902 13.7215 21.387 10.3082 19.7732 7.50153L18.9062 8ZM18.9062 16L18.0393 15.5015C16.7811 17.6898 14.4876 19 12 19V20V21C15.1999 21 18.1564 19.3102 19.7732 16.4985L18.9062 16ZM15.5312 10.5312V9.53125H15.5V10.5312V11.5312H15.5312V10.5312ZM15.5 10.5312L16.169 11.2745C16.9447 10.5764 16.8883 9.44281 16.2071 8.76164L15.5 9.46875L14.7929 10.1759C14.7696 10.1525 14.7344 10.0966 14.7344 10.0117C14.7344 9.92377 14.7735 9.83972 14.831 9.78796L15.5 10.5312ZM15.5 9.46875L16.2071 8.76164C15.5353 8.08987 14.4334 8.08987 13.7616 8.76164L14.4688 9.46875L15.1759 10.1759C15.1167 10.235 15.0442 10.2578 14.9844 10.2578C14.9245 10.2578 14.8521 10.235 14.7929 10.1759L15.5 9.46875ZM14.4688 9.46875L13.7585 8.76482L10.2897 12.2648L11 12.9688L11.7103 13.6727L15.179 10.1727L14.4688 9.46875ZM11 12.9688L11.7071 12.2616L10.2384 10.7929L9.53125 11.5L8.82414 12.2071L10.2929 13.6759L11 12.9688ZM9.53125 11.5L10.2384 10.7929C9.55719 10.1117 8.42362 10.0553 7.72546 10.831L8.46875 11.5L9.21204 12.169C9.16028 12.2265 9.07623 12.2656 8.98828 12.2656C8.90344 12.2656 8.84748 12.2304 8.82414 12.2071L9.53125 11.5ZM8.46875 11.5L7.79979 10.7567C7.04591 11.4352 7.04591 12.5961 7.79979 13.2745L8.46875 12.5312L9.13771 11.788C9.19301 11.8377 9.23438 11.9208 9.23438 12.0156C9.23438 12.1105 9.19301 12.1935 9.13771 12.2433L8.46875 11.5ZM8.46875 12.5312L7.76164 13.2384L9.76164 15.2384L10.4688 14.5312L11.1759 13.8241L9.17586 11.8241L8.46875 12.5312ZM10.4688 14.5312L9.72546 15.2002C10.4236 15.976 11.5572 15.9195 12.2384 15.2384L11.5312 14.5312L10.8241 13.8241C10.8475 13.8008 10.9034 13.7656 10.9883 13.7656C11.0762 13.7656 11.1603 13.8048 11.212 13.8623L10.4688 14.5312ZM11.5312 14.5312L12.2384 15.2384L16.2384 11.2384L15.5312 10.5312L14.8241 9.82414L10.8241 13.8241L11.5312 14.5312Z"
16
+ fill="white"
17
+ mask="url(#path-2-outside-1_3089_3799)"
18
+ />
19
+ </svg>
20
+ );
package/src/chart-type.js CHANGED
@@ -16,11 +16,15 @@ const ChartType = withStyles(() => ({
16
16
  }))(({ onChange, value, classes, availableChartTypes, chartTypeLabel }) => (
17
17
  <div className={classes.chartType}>
18
18
  <FormControl variant={'outlined'} className={classes.chartType}>
19
- <InputLabel htmlFor="type-helper" className={classes.chartTypeLabel}>
19
+ <InputLabel id="type-helper-label" className={classes.chartTypeLabel}>
20
20
  {chartTypeLabel}
21
21
  </InputLabel>
22
-
23
- <Select value={value} onChange={onChange} labelWidth={75} input={<OutlinedInput name="type" id="type-helper" />}>
22
+ <Select
23
+ labelId="type-helper-label"
24
+ value={value}
25
+ onChange={onChange}
26
+ input={<OutlinedInput labelWidth={75} name="type" />}
27
+ >
24
28
  {availableChartTypes?.histogram && <MenuItem value={'histogram'}>{availableChartTypes.histogram}</MenuItem>}
25
29
  {availableChartTypes?.bar && <MenuItem value={'bar'}>{availableChartTypes.bar}</MenuItem>}
26
30
  {availableChartTypes?.lineDot && <MenuItem value={'lineDot'}>{availableChartTypes.lineDot}</MenuItem>}
package/src/chart.jsx CHANGED
@@ -2,16 +2,16 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { withStyles } from '@material-ui/core/styles';
4
4
  import classNames from 'classnames';
5
- import { Root, createGraphProps } from '@pie-lib/plot';
5
+ import debug from 'debug';
6
6
  import cloneDeep from 'lodash/cloneDeep';
7
+
8
+ import { Root, createGraphProps } from '@pie-lib/plot';
9
+ import { AlertDialog } from '@pie-lib/config-ui';
7
10
  import ChartGrid from './grid';
8
11
  import ChartAxes from './axes';
9
- import debug from 'debug';
10
- import { color } from '@pie-lib/render-ui';
11
12
  import { dataToXBand, getDomainAndRangeByChartType, getGridLinesAndAxisByChartType, getTopPadding } from './utils';
12
- import ToolMenu from './tool-menu';
13
13
  import chartTypes from './chart-types';
14
- import { AlertDialog } from '@pie-lib/config-ui';
14
+ import ActionsButton from './actions-button';
15
15
  import Translator from '@pie-lib/translator';
16
16
 
17
17
  const { translator } = Translator;
@@ -25,6 +25,7 @@ export class Chart extends React.Component {
25
25
  dialog: {
26
26
  open: false,
27
27
  },
28
+ actionsAnchorEl: null,
28
29
  };
29
30
  this.maskUid = this.generateMaskId();
30
31
  }
@@ -70,6 +71,14 @@ export class Chart extends React.Component {
70
71
  changeInteractiveEnabled: PropTypes.bool,
71
72
  changeEditableEnabled: PropTypes.bool,
72
73
  language: PropTypes.string,
74
+ mathMlOptions: PropTypes.object,
75
+ labelsCharactersLimit: PropTypes.number,
76
+ correctData: PropTypes.arrayOf(
77
+ PropTypes.shape({
78
+ label: PropTypes.string,
79
+ value: PropTypes.number,
80
+ }),
81
+ ),
73
82
  };
74
83
 
75
84
  static defaultProps = {
@@ -88,6 +97,7 @@ export class Chart extends React.Component {
88
97
  chartTypes.DotPlot(),
89
98
  chartTypes.LinePlot(),
90
99
  ],
100
+ autoFocus: false,
91
101
  };
92
102
 
93
103
  generateMaskId() {
@@ -156,11 +166,11 @@ export class Chart extends React.Component {
156
166
  },
157
167
  });
158
168
  } else {
169
+ this.setState({ autoFocus: true });
159
170
  onDataChange([
160
171
  ...data,
161
172
  {
162
173
  inDefineChart: defineChart,
163
- autoFocus: true,
164
174
  label: categoryDefaultLabel || translator.t('charting.newLabel', { lng: language }),
165
175
  value: 0,
166
176
  deletable: true,
@@ -171,6 +181,18 @@ export class Chart extends React.Component {
171
181
  }
172
182
  };
173
183
 
184
+ deleteCategory = (index) => {
185
+ const { data, onDataChange } = this.props;
186
+
187
+ if (typeof index !== 'number' || index < 0) {
188
+ return;
189
+ }
190
+
191
+ if (data && data.length > 0) {
192
+ onDataChange(data.filter((_, i) => i !== index));
193
+ }
194
+ };
195
+
174
196
  getFilteredCategories = () => {
175
197
  const { data, defineChart } = this.props;
176
198
 
@@ -182,6 +204,10 @@ export class Chart extends React.Component {
182
204
  : [];
183
205
  };
184
206
 
207
+ resetAutoFocus = () => {
208
+ this.setState({ autoFocus: false });
209
+ };
210
+
185
211
  render() {
186
212
  const {
187
213
  classes,
@@ -202,6 +228,8 @@ export class Chart extends React.Component {
202
228
  error,
203
229
  mathMlOptions = {},
204
230
  language,
231
+ labelsCharactersLimit,
232
+ correctData,
205
233
  } = this.props;
206
234
  let { chartType } = this.props;
207
235
 
@@ -223,7 +251,7 @@ export class Chart extends React.Component {
223
251
 
224
252
  log('[render] common:', common);
225
253
 
226
- const maskSize = { x: -10, y: -75, width: width + 20, height: height + 80 };
254
+ const maskSize = { x: -10, y: -75, width: width + 20, height: height + 130 };
227
255
  const { scale } = common.graphProps;
228
256
  const xBand = dataToXBand(scale.x, categories, width, chartType);
229
257
 
@@ -244,15 +272,6 @@ export class Chart extends React.Component {
244
272
 
245
273
  return (
246
274
  <div className={classNames(classes.chart, classes.chartBox, className)}>
247
- <div className={classes.controls}>
248
- <ToolMenu
249
- className={classes.toolMenu}
250
- disabled={!addCategoryEnabled}
251
- addCategory={() => this.addCategory()}
252
- language={language}
253
- />
254
- </div>
255
-
256
275
  <Root
257
276
  title={title}
258
277
  onChangeTitle={onChangeTitle}
@@ -269,10 +288,13 @@ export class Chart extends React.Component {
269
288
  showPixelGuides={showPixelGuides}
270
289
  rootRef={(r) => (this.rootNode = r)}
271
290
  mathMlOptions={mathMlOptions}
291
+ labelsCharactersLimit={labelsCharactersLimit}
272
292
  {...rootCommon}
273
293
  >
274
294
  <ChartGrid {...common} xBand={xBand} rowTickValues={horizontalLines} columnTickValues={verticalLines} />
275
295
  <ChartAxes
296
+ autoFocus={this.state.autoFocus}
297
+ onAutoFocusUsed={this.resetAutoFocus}
276
298
  {...common}
277
299
  defineChart={defineChart}
278
300
  categories={categories}
@@ -285,7 +307,20 @@ export class Chart extends React.Component {
285
307
  changeEditableEnabled={changeEditableEnabled}
286
308
  top={top}
287
309
  error={error}
310
+ showCorrectness={chartType === 'linePlot' || chartType === 'dotPlot'}
288
311
  />
312
+ {addCategoryEnabled ? (
313
+ <foreignObject x={width} y={height - 16} width={width} height={height}>
314
+ <div xmlns="http://www.w3.org/1999/xhtml" style={{ display: 'flex', justifyContent: 'flex-start' }}>
315
+ <ActionsButton
316
+ categories={categories}
317
+ addCategory={this.addCategory}
318
+ deleteCategory={this.deleteCategory}
319
+ language={language}
320
+ />
321
+ </div>
322
+ </foreignObject>
323
+ ) : null}
289
324
  <mask id={`${this.maskUid}`}>
290
325
  <rect {...maskSize} fill="white" />
291
326
  </mask>
@@ -297,6 +332,7 @@ export class Chart extends React.Component {
297
332
  defineChart={defineChart}
298
333
  onChange={this.changeData}
299
334
  onChangeCategory={this.changeCategory}
335
+ correctData={correctData}
300
336
  />
301
337
  </g>
302
338
  </Root>
@@ -316,22 +352,10 @@ const styles = (theme) => ({
316
352
  graphBox: {
317
353
  transform: 'translate(60px, 35px)',
318
354
  },
319
- controls: {
320
- display: 'flex',
321
- justifyContent: 'space-between',
322
- padding: theme.spacing.unit,
323
- backgroundColor: color.primaryLight(),
324
- borderTop: `solid 1px ${color.primaryDark()}`,
325
- borderBottom: `solid 0px ${color.primaryDark()}`,
326
- borderLeft: `solid 1px ${color.primaryDark()}`,
327
- borderRight: `solid 1px ${color.primaryDark()}`,
328
- },
329
355
  svg: {
330
356
  overflow: 'visible',
331
357
  },
332
- toolMenu: {
333
- minHeight: '36px',
334
- },
358
+
335
359
  chartBox: {
336
360
  width: 'min-content',
337
361
  },
@@ -0,0 +1,48 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`BasePoint snapshot renders 1`] = `
4
+ <RawDragHandle
5
+ className="className"
6
+ classes={
7
+ Object {
8
+ "correctIcon": "RawDragHandle-correctIcon-5",
9
+ "correctnessIcon": "RawDragHandle-correctnessIcon-7",
10
+ "handle": "RawDragHandle-handle-1",
11
+ "handleContainer": "RawDragHandle-handleContainer-3",
12
+ "incorrectIcon": "RawDragHandle-incorrectIcon-6",
13
+ "svgOverflowVisible": "RawDragHandle-svgOverflowVisible-4",
14
+ "transparentHandle": "RawDragHandle-transparentHandle-2",
15
+ }
16
+ }
17
+ graphProps={
18
+ Object {
19
+ "domain": Object {
20
+ "max": 1,
21
+ "min": 0,
22
+ "step": 1,
23
+ },
24
+ "range": Object {
25
+ "max": 1,
26
+ "min": 0,
27
+ "step": 1,
28
+ },
29
+ "scale": Object {
30
+ "x": [MockFunction],
31
+ "y": [MockFunction],
32
+ },
33
+ "size": Object {
34
+ "height": 400,
35
+ "width": 400,
36
+ },
37
+ "snap": Object {
38
+ "x": [MockFunction],
39
+ "y": [MockFunction],
40
+ },
41
+ }
42
+ }
43
+ onChange={[MockFunction]}
44
+ width={100}
45
+ x={0}
46
+ y={0}
47
+ />
48
+ `;
@@ -0,0 +1,88 @@
1
+ import { shallow } from 'enzyme/build';
2
+ import React from 'react';
3
+ import DragHandle from '../drag-handle';
4
+ import { gridDraggable } from '@pie-lib/plot';
5
+ import { graphProps } from './utils';
6
+ import { bounds } from '../../utils';
7
+
8
+ jest.mock('../../utils', () => {
9
+ const { point } = jest.requireActual('../../utils');
10
+ return {
11
+ bounds: jest.fn(),
12
+ point,
13
+ };
14
+ });
15
+
16
+ jest.mock('@pie-lib/plot', () => {
17
+ const { types, utils } = jest.requireActual('@pie-lib/plot');
18
+ return {
19
+ gridDraggable: jest.fn((opts) => (Comp) => Comp),
20
+ types,
21
+ utils,
22
+ };
23
+ });
24
+
25
+ describe('BasePoint', () => {
26
+ let w;
27
+ let onChange = jest.fn();
28
+ const wrapper = (extras) => {
29
+ const defaults = {
30
+ classes: {},
31
+ className: 'className',
32
+ onChange,
33
+ graphProps: graphProps(),
34
+ x: 0,
35
+ y: 0,
36
+ width: 100,
37
+ };
38
+ const props = { ...defaults, ...extras };
39
+ return shallow(<DragHandle {...props} />);
40
+ };
41
+
42
+ describe('snapshot', () => {
43
+ it('renders', () => {
44
+ w = wrapper();
45
+ expect(w).toMatchSnapshot();
46
+ });
47
+ });
48
+ describe('gridDraggable options', () => {
49
+ let opts;
50
+ let domain;
51
+ let range;
52
+ beforeEach(() => {
53
+ domain = {
54
+ min: 0,
55
+ max: 1,
56
+ step: 1,
57
+ };
58
+ range = {
59
+ min: 0,
60
+ max: 1,
61
+ step: 1,
62
+ };
63
+ const w = wrapper();
64
+ opts = gridDraggable.mock.calls[0][0];
65
+ });
66
+
67
+ describe('bounds', () => {
68
+ it('calls utils.bounds with area', () => {
69
+ const result = opts.bounds({ x: 0, y: 0 }, { domain, range });
70
+
71
+ expect(result).toEqual({ left: 0, top: 1, bottom: 0, right: 1 });
72
+ });
73
+ });
74
+ describe('anchorPoint', () => {
75
+ it('returns x/y', () => {
76
+ const result = opts.anchorPoint({ x: 0, y: 0 });
77
+ expect(result).toEqual({ x: 0, y: 0 });
78
+ });
79
+ });
80
+
81
+ describe('fromDelta', () => {
82
+ it('returns y coordinate of a new point from the x/y + delta', () => {
83
+ const result = opts.fromDelta({ x: -1, y: 0 }, { x: 1, y: 3 });
84
+ expect(result).toEqual(3);
85
+ });
86
+ });
87
+ });
88
+ });
@@ -0,0 +1,30 @@
1
+ export const scaleMock = () => {
2
+ const fn = jest.fn((n) => n);
3
+ fn.invert = jest.fn((n) => n);
4
+ return fn;
5
+ };
6
+
7
+ export const graphProps = (dmin = 0, dmax = 1, rmin = 0, rmax = 1) => ({
8
+ scale: {
9
+ x: scaleMock(),
10
+ y: scaleMock(),
11
+ },
12
+ snap: {
13
+ x: jest.fn((n) => n),
14
+ y: jest.fn((n) => n),
15
+ },
16
+ domain: {
17
+ min: dmin,
18
+ max: dmax,
19
+ step: 1,
20
+ },
21
+ range: {
22
+ min: rmin,
23
+ max: rmax,
24
+ step: 1,
25
+ },
26
+ size: {
27
+ width: 400,
28
+ height: 400,
29
+ },
30
+ });