@pie-lib/graphing 3.1.1-next.0 → 3.2.0-next.0

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 (198) hide show
  1. package/lib/axis/arrow.js +0 -3
  2. package/lib/axis/arrow.js.map +1 -1
  3. package/lib/axis/axes.js +0 -16
  4. package/lib/axis/axes.js.map +1 -1
  5. package/lib/axis/index.js +0 -7
  6. package/lib/axis/index.js.map +1 -1
  7. package/lib/bg.js +0 -6
  8. package/lib/bg.js.map +1 -1
  9. package/lib/container/actions.js +0 -1
  10. package/lib/container/actions.js.map +1 -1
  11. package/lib/container/index.js +4 -8
  12. package/lib/container/index.js.map +1 -1
  13. package/lib/container/marks.js +0 -2
  14. package/lib/container/marks.js.map +1 -1
  15. package/lib/container/middleware.js +0 -1
  16. package/lib/container/middleware.js.map +1 -1
  17. package/lib/container/reducer.js +0 -1
  18. package/lib/container/reducer.js.map +1 -1
  19. package/lib/coordinates-label.js +0 -11
  20. package/lib/coordinates-label.js.map +1 -1
  21. package/lib/graph-with-controls.js +3 -21
  22. package/lib/graph-with-controls.js.map +1 -1
  23. package/lib/graph.js +8 -27
  24. package/lib/graph.js.map +1 -1
  25. package/lib/grid-setup.js +0 -11
  26. package/lib/grid-setup.js.map +1 -1
  27. package/lib/grid.js +0 -22
  28. package/lib/grid.js.map +1 -1
  29. package/lib/index.js +0 -7
  30. package/lib/index.js.map +1 -1
  31. package/lib/key-legend.js +1 -2
  32. package/lib/key-legend.js.map +1 -1
  33. package/lib/label-svg-icon.js +0 -1
  34. package/lib/label-svg-icon.js.map +1 -1
  35. package/lib/labels.js +0 -13
  36. package/lib/labels.js.map +1 -1
  37. package/lib/mark-label.js +0 -15
  38. package/lib/mark-label.js.map +1 -1
  39. package/lib/toggle-bar.js +0 -17
  40. package/lib/toggle-bar.js.map +1 -1
  41. package/lib/tool-menu.js +0 -3
  42. package/lib/tool-menu.js.map +1 -1
  43. package/lib/tools/absolute/component.js +0 -1
  44. package/lib/tools/absolute/component.js.map +1 -1
  45. package/lib/tools/absolute/index.js +0 -10
  46. package/lib/tools/absolute/index.js.map +1 -1
  47. package/lib/tools/circle/bg-circle.js +0 -15
  48. package/lib/tools/circle/bg-circle.js.map +1 -1
  49. package/lib/tools/circle/component.js +2 -15
  50. package/lib/tools/circle/component.js.map +1 -1
  51. package/lib/tools/circle/index.js +0 -10
  52. package/lib/tools/circle/index.js.map +1 -1
  53. package/lib/tools/exponential/component.js +0 -1
  54. package/lib/tools/exponential/component.js.map +1 -1
  55. package/lib/tools/exponential/index.js +0 -10
  56. package/lib/tools/exponential/index.js.map +1 -1
  57. package/lib/tools/index.js +0 -1
  58. package/lib/tools/index.js.map +1 -1
  59. package/lib/tools/line/component.js +0 -2
  60. package/lib/tools/line/component.js.map +1 -1
  61. package/lib/tools/line/index.js +0 -1
  62. package/lib/tools/line/index.js.map +1 -1
  63. package/lib/tools/parabola/component.js +0 -1
  64. package/lib/tools/parabola/component.js.map +1 -1
  65. package/lib/tools/parabola/index.js +0 -10
  66. package/lib/tools/parabola/index.js.map +1 -1
  67. package/lib/tools/point/component.js +3 -15
  68. package/lib/tools/point/component.js.map +1 -1
  69. package/lib/tools/point/index.js +0 -10
  70. package/lib/tools/point/index.js.map +1 -1
  71. package/lib/tools/polygon/component.js +5 -29
  72. package/lib/tools/polygon/component.js.map +1 -1
  73. package/lib/tools/polygon/index.js +0 -12
  74. package/lib/tools/polygon/index.js.map +1 -1
  75. package/lib/tools/polygon/line.js +0 -15
  76. package/lib/tools/polygon/line.js.map +1 -1
  77. package/lib/tools/polygon/polygon.js +0 -18
  78. package/lib/tools/polygon/polygon.js.map +1 -1
  79. package/lib/tools/ray/component.js +0 -11
  80. package/lib/tools/ray/component.js.map +1 -1
  81. package/lib/tools/ray/index.js +0 -1
  82. package/lib/tools/ray/index.js.map +1 -1
  83. package/lib/tools/segment/component.js +0 -10
  84. package/lib/tools/segment/component.js.map +1 -1
  85. package/lib/tools/segment/index.js +0 -1
  86. package/lib/tools/segment/index.js.map +1 -1
  87. package/lib/tools/shared/arrow-head.js +0 -14
  88. package/lib/tools/shared/arrow-head.js.map +1 -1
  89. package/lib/tools/shared/icons/CorrectSVG.js +0 -1
  90. package/lib/tools/shared/icons/CorrectSVG.js.map +1 -1
  91. package/lib/tools/shared/icons/IncorrectSVG.js +0 -1
  92. package/lib/tools/shared/icons/IncorrectSVG.js.map +1 -1
  93. package/lib/tools/shared/icons/MissingSVG.js +0 -1
  94. package/lib/tools/shared/icons/MissingSVG.js.map +1 -1
  95. package/lib/tools/shared/line/index.js +7 -21
  96. package/lib/tools/shared/line/index.js.map +1 -1
  97. package/lib/tools/shared/line/line-path.js +0 -15
  98. package/lib/tools/shared/line/line-path.js.map +1 -1
  99. package/lib/tools/shared/line/with-root-edge.js +0 -11
  100. package/lib/tools/shared/line/with-root-edge.js.map +1 -1
  101. package/lib/tools/shared/point/arrow-point.js +0 -3
  102. package/lib/tools/shared/point/arrow-point.js.map +1 -1
  103. package/lib/tools/shared/point/arrow.js +0 -3
  104. package/lib/tools/shared/point/arrow.js.map +1 -1
  105. package/lib/tools/shared/point/base-point.js +0 -16
  106. package/lib/tools/shared/point/base-point.js.map +1 -1
  107. package/lib/tools/shared/point/index.js +0 -7
  108. package/lib/tools/shared/point/index.js.map +1 -1
  109. package/lib/tools/shared/styles.js +0 -1
  110. package/lib/tools/shared/styles.js.map +1 -1
  111. package/lib/tools/shared/types.js +0 -1
  112. package/lib/tools/shared/types.js.map +1 -1
  113. package/lib/tools/sine/component.js +0 -10
  114. package/lib/tools/sine/component.js.map +1 -1
  115. package/lib/tools/sine/index.js +0 -10
  116. package/lib/tools/sine/index.js.map +1 -1
  117. package/lib/tools/vector/component.js +0 -10
  118. package/lib/tools/vector/component.js.map +1 -1
  119. package/lib/tools/vector/index.js +0 -1
  120. package/lib/tools/vector/index.js.map +1 -1
  121. package/lib/undo-redo.js +0 -2
  122. package/lib/undo-redo.js.map +1 -1
  123. package/lib/use-debounce.js +0 -2
  124. package/lib/use-debounce.js.map +1 -1
  125. package/lib/utils.js +9 -26
  126. package/lib/utils.js.map +1 -1
  127. package/package.json +13 -10
  128. package/src/__tests__/bg.test.jsx +250 -0
  129. package/src/__tests__/coordinates-label.test.jsx +243 -0
  130. package/src/__tests__/graph-with-controls.test.jsx +9 -16
  131. package/src/__tests__/graph.test.jsx +560 -5
  132. package/src/__tests__/grid-setup.test.jsx +645 -0
  133. package/src/__tests__/grid.test.jsx +1 -1
  134. package/src/__tests__/key-legend.test.jsx +260 -0
  135. package/src/__tests__/label-svg-icon.test.jsx +278 -0
  136. package/src/__tests__/mark-label.test.jsx +1 -1
  137. package/src/__tests__/toggle-bar.test.jsx +0 -6
  138. package/src/__tests__/tool-menu.test.jsx +0 -4
  139. package/src/__tests__/use-debounce.test.js +1 -1
  140. package/src/__tests__/utils.test.js +15 -61
  141. package/src/axis/__tests__/axes.test.jsx +1 -1
  142. package/src/axis/axes.jsx +7 -21
  143. package/src/axis/index.js +1 -0
  144. package/src/bg.jsx +1 -1
  145. package/src/container/__tests__/actions.test.js +105 -0
  146. package/src/container/__tests__/index.test.jsx +319 -0
  147. package/src/container/__tests__/marks.test.js +172 -0
  148. package/src/container/__tests__/middleware.test.js +235 -0
  149. package/src/container/__tests__/reducer.test.js +324 -0
  150. package/src/container/index.jsx +2 -3
  151. package/src/coordinates-label.jsx +1 -7
  152. package/src/graph-with-controls.jsx +8 -6
  153. package/src/graph.jsx +2 -3
  154. package/src/grid-setup.jsx +1 -1
  155. package/src/key-legend.jsx +2 -1
  156. package/src/mark-label.jsx +7 -24
  157. package/src/toggle-bar.jsx +8 -1
  158. package/src/tools/absolute/__tests__/component.test.jsx +1 -2
  159. package/src/tools/absolute/component.jsx +2 -2
  160. package/src/tools/circle/__tests__/component.test.jsx +438 -0
  161. package/src/tools/circle/__tests__/index.test.js +480 -0
  162. package/src/tools/circle/bg-circle.jsx +2 -2
  163. package/src/tools/circle/component.jsx +10 -12
  164. package/src/tools/exponential/__tests__/component.test.jsx +0 -1
  165. package/src/tools/exponential/__tests__/index.test.js +729 -0
  166. package/src/tools/exponential/component.jsx +1 -1
  167. package/src/tools/line/__tests__/component.test.jsx +1 -0
  168. package/src/tools/line/component.jsx +4 -11
  169. package/src/tools/parabola/__tests__/component.test.jsx +0 -1
  170. package/src/tools/parabola/__tests__/index.test.js +470 -0
  171. package/src/tools/parabola/component.jsx +1 -1
  172. package/src/tools/point/__tests__/component.test.jsx +310 -2
  173. package/src/tools/point/__tests__/index.test.js +241 -0
  174. package/src/tools/point/component.jsx +1 -2
  175. package/src/tools/polygon/__tests__/component.test.jsx +391 -2
  176. package/src/tools/polygon/__tests__/index.test.js +237 -8
  177. package/src/tools/polygon/__tests__/line.test.jsx +13 -0
  178. package/src/tools/polygon/__tests__/polygon.test.jsx +19 -1
  179. package/src/tools/polygon/component.jsx +4 -14
  180. package/src/tools/polygon/line.jsx +1 -1
  181. package/src/tools/polygon/polygon.jsx +1 -1
  182. package/src/tools/ray/__tests__/component.test.jsx +1 -0
  183. package/src/tools/ray/component.jsx +3 -5
  184. package/src/tools/segment/__tests__/component.test.jsx +1 -0
  185. package/src/tools/segment/component.jsx +1 -1
  186. package/src/tools/shared/arrow-head.jsx +11 -6
  187. package/src/tools/shared/line/__tests__/index.test.jsx +1 -1
  188. package/src/tools/shared/line/__tests__/line-path.test.jsx +3 -3
  189. package/src/tools/shared/line/__tests__/with-root-edge.test.jsx +2 -2
  190. package/src/tools/shared/line/index.jsx +4 -6
  191. package/src/tools/shared/line/line-path.jsx +2 -8
  192. package/src/tools/shared/point/arrow-point.jsx +2 -5
  193. package/src/tools/sine/component.jsx +2 -2
  194. package/src/tools/vector/component.jsx +1 -1
  195. package/src/undo-redo.jsx +3 -9
  196. package/src/use-debounce.js +1 -1
  197. package/src/utils.js +1 -5
  198. package/NEXT.CHANGELOG.json +0 -16
@@ -0,0 +1,243 @@
1
+ import React from 'react';
2
+ import { render } from '@pie-lib/test-utils';
3
+ import { CoordinatesLabel, getLabelPosition } from '../coordinates-label';
4
+
5
+ describe('CoordinatesLabel', () => {
6
+ let defaultProps;
7
+ let graphProps;
8
+
9
+ beforeEach(() => {
10
+ graphProps = {
11
+ domain: { min: -10, max: 10, step: 1, label: 'x', axisLabel: 'X' },
12
+ range: { min: -10, max: 10, step: 1, label: 'y', axisLabel: 'Y' },
13
+ scale: {
14
+ x: jest.fn((val) => (val + 10) * 20),
15
+ y: jest.fn((val) => (10 - val) * 20),
16
+ },
17
+ };
18
+
19
+ defaultProps = {
20
+ x: 5,
21
+ y: 5,
22
+ graphProps,
23
+ };
24
+ });
25
+
26
+ describe('rendering', () => {
27
+ it('renders without crashing', () => {
28
+ const { container } = render(<CoordinatesLabel {...defaultProps} />);
29
+ expect(container).toBeTruthy();
30
+ });
31
+
32
+ it('displays formatted coordinates', () => {
33
+ const { container } = render(<CoordinatesLabel {...defaultProps} />);
34
+ const input = container.querySelector('input');
35
+
36
+ expect(input.value).toBe('(5, 5)');
37
+ });
38
+
39
+ it('rounds coordinates to 4 decimal places', () => {
40
+ const props = { ...defaultProps, x: 1.123456, y: 2.987654 };
41
+ const { container } = render(<CoordinatesLabel {...props} />);
42
+ const input = container.querySelector('input');
43
+
44
+ expect(input.value).toBe('(1.1235, 2.9877)');
45
+ });
46
+
47
+ it('handles integer coordinates', () => {
48
+ const props = { ...defaultProps, x: 0, y: 0 };
49
+ const { container } = render(<CoordinatesLabel {...props} />);
50
+ const input = container.querySelector('input');
51
+
52
+ expect(input.value).toBe('(0, 0)');
53
+ });
54
+
55
+ it('handles negative coordinates', () => {
56
+ const props = { ...defaultProps, x: -3, y: -7 };
57
+ const { container } = render(<CoordinatesLabel {...props} />);
58
+ const input = container.querySelector('input');
59
+
60
+ expect(input.value).toBe('(-3, -7)');
61
+ });
62
+
63
+ it('renders as an input element', () => {
64
+ const { container } = render(<CoordinatesLabel {...defaultProps} />);
65
+ const input = container.querySelector('input');
66
+
67
+ expect(input).toBeTruthy();
68
+ expect(input.tagName).toBe('INPUT');
69
+ });
70
+
71
+ it('applies correct styles', () => {
72
+ const { container } = render(<CoordinatesLabel {...defaultProps} />);
73
+ const wrapper = container.firstChild;
74
+
75
+ expect(wrapper).toHaveStyle({ position: 'absolute' });
76
+ expect(wrapper).toHaveStyle({ pointerEvents: 'auto' });
77
+ });
78
+ });
79
+
80
+ describe('getLabelPosition', () => {
81
+ it('positions label to the right by default', () => {
82
+ const position = getLabelPosition(graphProps, 0, 0, 60);
83
+
84
+ expect(position.left).toBeGreaterThan(graphProps.scale.x(0));
85
+ expect(position.top).toBeDefined();
86
+ });
87
+
88
+ it('positions label to the left when near right edge', () => {
89
+ const x = 9; // Near max
90
+ const labelLength = 100;
91
+ const position = getLabelPosition(graphProps, x, 0, labelLength);
92
+
93
+ expect(position.left).toBeLessThan(graphProps.scale.x(x));
94
+ });
95
+
96
+ it('adjusts top position for minimum y value', () => {
97
+ const position = getLabelPosition(graphProps, 0, -10, 60);
98
+
99
+ expect(position.top).toBe(graphProps.scale.y(-10) - 16);
100
+ });
101
+
102
+ it('adjusts top position for maximum y value', () => {
103
+ const position = getLabelPosition(graphProps, 0, 10, 60);
104
+
105
+ expect(position.top).toBe(graphProps.scale.y(10) - 0);
106
+ });
107
+
108
+ it('centers label vertically for middle values', () => {
109
+ const position = getLabelPosition(graphProps, 0, 0, 60);
110
+
111
+ expect(position.top).toBe(graphProps.scale.y(0) - 8);
112
+ });
113
+
114
+ it('applies left shift consistently', () => {
115
+ const leftShift = 10;
116
+ const labelLength = 60;
117
+
118
+ const rightPos = getLabelPosition(graphProps, 0, 0, labelLength);
119
+ expect(rightPos.left).toBe(graphProps.scale.x(0) + leftShift);
120
+
121
+ const leftPos = getLabelPosition(graphProps, 9, 0, labelLength);
122
+ expect(leftPos.left).toBe(graphProps.scale.x(9) - leftShift - labelLength);
123
+ });
124
+ });
125
+
126
+ describe('label width calculation', () => {
127
+ it('calculates width based on label length', () => {
128
+ const props = { ...defaultProps, x: 1, y: 2 };
129
+ const { container } = render(<CoordinatesLabel {...props} />);
130
+ const wrapper = container.firstChild;
131
+
132
+ const expectedWidth = 6 * 6;
133
+ expect(wrapper).toHaveStyle({ width: `${expectedWidth}px` });
134
+ });
135
+
136
+ it('adjusts width for longer coordinates', () => {
137
+ const props = { ...defaultProps, x: -10.123, y: 10.456 };
138
+ const { container } = render(<CoordinatesLabel {...props} />);
139
+ const wrapper = container.firstChild;
140
+
141
+ const style = window.getComputedStyle(wrapper);
142
+ expect(parseInt(style.width)).toBeGreaterThan(42);
143
+ });
144
+ });
145
+
146
+ describe('edge cases', () => {
147
+ it('handles very small coordinates', () => {
148
+ const props = { ...defaultProps, x: 0.0001, y: 0.0002 };
149
+ const { container } = render(<CoordinatesLabel {...props} />);
150
+ const input = container.querySelector('input');
151
+
152
+ expect(input.value).toContain('(');
153
+ expect(input.value).toContain(')');
154
+ expect(input.value).toContain(',');
155
+ });
156
+
157
+ it('handles very large coordinates', () => {
158
+ const props = { ...defaultProps, x: 999999, y: 888888 };
159
+ const { container } = render(<CoordinatesLabel {...props} />);
160
+ const input = container.querySelector('input');
161
+
162
+ expect(input.value).toBe('(999999, 888888)');
163
+ });
164
+
165
+ it('handles zero coordinates', () => {
166
+ const props = { ...defaultProps, x: 0, y: 0 };
167
+ const { container } = render(<CoordinatesLabel {...props} />);
168
+ const input = container.querySelector('input');
169
+
170
+ expect(input.value).toBe('(0, 0)');
171
+ });
172
+
173
+ it('handles coordinates at domain/range boundaries', () => {
174
+ const props = { ...defaultProps, x: 10, y: 10 };
175
+ const { container } = render(<CoordinatesLabel {...props} />);
176
+ const input = container.querySelector('input');
177
+
178
+ expect(input.value).toBe('(10, 10)');
179
+ });
180
+
181
+ it('handles negative boundaries', () => {
182
+ const props = { ...defaultProps, x: -10, y: -10 };
183
+ const { container } = render(<CoordinatesLabel {...props} />);
184
+ const input = container.querySelector('input');
185
+
186
+ expect(input.value).toBe('(-10, -10)');
187
+ });
188
+ });
189
+
190
+ describe('prop types and validation', () => {
191
+ it('accepts required props', () => {
192
+ expect(() => {
193
+ render(<CoordinatesLabel {...defaultProps} />);
194
+ }).not.toThrow();
195
+ });
196
+
197
+ it('renders with missing optional props', () => {
198
+ const props = {
199
+ x: 1,
200
+ y: 2,
201
+ graphProps,
202
+ };
203
+
204
+ expect(() => {
205
+ render(<CoordinatesLabel {...props} />);
206
+ }).not.toThrow();
207
+ });
208
+ });
209
+
210
+ describe('updates', () => {
211
+ it('updates when x coordinate changes', () => {
212
+ const { container, rerender } = render(<CoordinatesLabel {...defaultProps} />);
213
+ let input = container.querySelector('input');
214
+ expect(input.value).toBe('(5, 5)');
215
+
216
+ rerender(<CoordinatesLabel {...defaultProps} x={7} />);
217
+ input = container.querySelector('input');
218
+ expect(input.value).toBe('(7, 5)');
219
+ });
220
+
221
+ it('updates when y coordinate changes', () => {
222
+ const { container, rerender } = render(<CoordinatesLabel {...defaultProps} />);
223
+ let input = container.querySelector('input');
224
+ expect(input.value).toBe('(5, 5)');
225
+
226
+ rerender(<CoordinatesLabel {...defaultProps} y={3} />);
227
+ input = container.querySelector('input');
228
+ expect(input.value).toBe('(5, 3)');
229
+ });
230
+
231
+ it('updates position when coordinates change', () => {
232
+ const { container, rerender } = render(<CoordinatesLabel {...defaultProps} />);
233
+ const initialStyle = window.getComputedStyle(container.firstChild);
234
+ const initialLeft = initialStyle.left;
235
+
236
+ rerender(<CoordinatesLabel {...defaultProps} x={8} />);
237
+ const newStyle = window.getComputedStyle(container.firstChild);
238
+ const newLeft = newStyle.left;
239
+
240
+ expect(newLeft).not.toBe(initialLeft);
241
+ });
242
+ });
243
+ });
@@ -1,14 +1,19 @@
1
1
  import { render } from '@pie-lib/test-utils';
2
2
  import React from 'react';
3
+ import {
4
+ filterByValidToolTypes,
5
+ filterByVisibleToolTypes,
6
+ getAvailableTool,
7
+ GraphWithControls,
8
+ setToolbarAvailability,
9
+ toolIsAvailable,
10
+ } from '../graph-with-controls';
11
+ import { allTools, line as lineTool, point as pointTool, toolsArr } from '../tools';
3
12
 
4
- import { xy } from './utils';
5
-
6
- // Mock DragProvider to avoid @dnd-kit React version conflicts
7
13
  jest.mock('@pie-lib/drag', () => ({
8
14
  DragProvider: ({ children }) => <div data-testid="drag-provider">{children}</div>,
9
15
  }));
10
16
 
11
- // Mock @dnd-kit/core hooks to avoid DndContext requirement
12
17
  jest.mock('@dnd-kit/core', () => ({
13
18
  useDraggable: jest.fn(() => ({
14
19
  attributes: {
@@ -30,7 +35,6 @@ jest.mock('@dnd-kit/core', () => ({
30
35
  })),
31
36
  }));
32
37
 
33
- // Mock @dnd-kit/utilities for CSS transform
34
38
  jest.mock('@dnd-kit/utilities', () => ({
35
39
  CSS: {
36
40
  Transform: {
@@ -39,7 +43,6 @@ jest.mock('@dnd-kit/utilities', () => ({
39
43
  },
40
44
  }));
41
45
 
42
- // Mock @dnd-kit/sortable for arrayMove
43
46
  jest.mock('@dnd-kit/sortable', () => ({
44
47
  arrayMove: jest.fn((array, from, to) => {
45
48
  const newArray = [...array];
@@ -49,16 +52,6 @@ jest.mock('@dnd-kit/sortable', () => ({
49
52
  }),
50
53
  }));
51
54
 
52
- import {
53
- GraphWithControls,
54
- setToolbarAvailability,
55
- toolIsAvailable,
56
- getAvailableTool,
57
- filterByValidToolTypes,
58
- filterByVisibleToolTypes,
59
- } from '../graph-with-controls';
60
- import { toolsArr, allTools, line as lineTool, point as pointTool } from '../tools';
61
-
62
55
  const point = {
63
56
  type: 'point',
64
57
  x: 2,