@khanacademy/perseus 19.1.3 → 19.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/components/graphie.d.ts +9 -1
- package/dist/es/index.js +275 -174
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +289 -158
- package/dist/index.js.map +1 -1
- package/dist/interactive2/interactive-util.d.ts +2 -2
- package/dist/interactive2/movable-point-options.d.ts +5 -4
- package/dist/interactive2/movable.d.ts +98 -2
- package/dist/interactive2/types.d.ts +6 -0
- package/dist/util/graphie.d.ts +6 -1
- package/dist/widgets/expression.d.ts +4 -4
- package/package.json +3 -3
- package/src/components/graphie.tsx +9 -1
- package/src/interactive2/__tests__/movable-mock.ts +43 -30
- package/src/interactive2/interactive-util.test.ts +93 -0
- package/src/interactive2/interactive-util.ts +19 -15
- package/src/interactive2/movable-helper-methods.ts +7 -2
- package/src/interactive2/movable-line.ts +1 -12
- package/src/interactive2/movable-point-options.ts +31 -19
- package/src/interactive2/movable-point.tsx +1 -9
- package/src/interactive2/movable-polygon.ts +1 -9
- package/src/interactive2/movable.test.ts +249 -0
- package/src/interactive2/movable.ts +313 -150
- package/src/interactive2/types.ts +15 -0
- package/src/interactive2.ts +1 -1
- package/src/util/graphie.ts +13 -1
- package/src/util/interactive.ts +4 -2
- package/tsconfig-build.tsbuildinfo +1 -1
|
@@ -15,10 +15,6 @@ import objective_ from "./objective_";
|
|
|
15
15
|
const assert = InteractiveUtil.assert;
|
|
16
16
|
const normalizeOptions = InteractiveUtil.normalizeOptions;
|
|
17
17
|
|
|
18
|
-
// State parameters that should be converted into an array of
|
|
19
|
-
// functions
|
|
20
|
-
const FUNCTION_ARRAY_OPTIONS = _.keys(MovablePolygonOptions);
|
|
21
|
-
|
|
22
18
|
// Default "props" and "state". Both are added to this.state and
|
|
23
19
|
// receive magic getter methods (this.points() etc).
|
|
24
20
|
// However, properties in DEFAULT_PROPS are updated on `modify()`,
|
|
@@ -89,7 +85,6 @@ _.extend(MovablePolygon.prototype, {
|
|
|
89
85
|
id: this.state.id,
|
|
90
86
|
},
|
|
91
87
|
normalizeOptions(
|
|
92
|
-
FUNCTION_ARRAY_OPTIONS,
|
|
93
88
|
// Defaults are copied from MovablePolygonOptions.*.standard
|
|
94
89
|
// These defaults are set here instead of DEFAULT_PROPS/STATE
|
|
95
90
|
// because they:
|
|
@@ -124,10 +119,7 @@ _.extend(MovablePolygon.prototype, {
|
|
|
124
119
|
update: function (options) {
|
|
125
120
|
const self = this;
|
|
126
121
|
const graphie = self.graphie;
|
|
127
|
-
const state = _.extend(
|
|
128
|
-
self.state,
|
|
129
|
-
normalizeOptions(FUNCTION_ARRAY_OPTIONS, options),
|
|
130
|
-
);
|
|
122
|
+
const state = _.extend(self.state, normalizeOptions(options));
|
|
131
123
|
|
|
132
124
|
// Default things inside the state.normalStyle object, because
|
|
133
125
|
// _.extend is not deep.
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import {fireEvent} from "@testing-library/react";
|
|
2
|
+
|
|
3
|
+
import {Graphie} from "../util/graphie";
|
|
4
|
+
|
|
5
|
+
import {Movable} from "./movable";
|
|
6
|
+
|
|
7
|
+
// Yay for side-effect imports!
|
|
8
|
+
// eslint-disable-next-line import/no-unassigned-import
|
|
9
|
+
import "../util/interactive";
|
|
10
|
+
|
|
11
|
+
describe("Movable", () => {
|
|
12
|
+
const properties = [
|
|
13
|
+
"graphie",
|
|
14
|
+
"state",
|
|
15
|
+
"prevState",
|
|
16
|
+
"cursor",
|
|
17
|
+
"added",
|
|
18
|
+
"isHovering",
|
|
19
|
+
"isMouseOver",
|
|
20
|
+
"isDragging",
|
|
21
|
+
"mouseTarget",
|
|
22
|
+
"_fireEvent",
|
|
23
|
+
"_applyConstraints",
|
|
24
|
+
"draw",
|
|
25
|
+
"listen",
|
|
26
|
+
"unlisten",
|
|
27
|
+
"cloneState",
|
|
28
|
+
"_createDefaultState",
|
|
29
|
+
"modify",
|
|
30
|
+
"grab",
|
|
31
|
+
"update",
|
|
32
|
+
"remove",
|
|
33
|
+
"toBack",
|
|
34
|
+
"toFront",
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
it.each(properties)("has a %s property", (property) => {
|
|
38
|
+
const dummyGraphie: any = {};
|
|
39
|
+
const movable = new Movable(dummyGraphie, {});
|
|
40
|
+
expect(movable[property]).toBeDefined();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const getters = [
|
|
44
|
+
"cursor",
|
|
45
|
+
"added",
|
|
46
|
+
"isHovering",
|
|
47
|
+
"isMouseOver",
|
|
48
|
+
"isDragging",
|
|
49
|
+
"mouseTarget",
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
it.each(getters)(
|
|
53
|
+
"returns the corresponding state property from %s()",
|
|
54
|
+
(getter) => {
|
|
55
|
+
const dummyGraphie: any = {};
|
|
56
|
+
const movable = new Movable(dummyGraphie, {});
|
|
57
|
+
expect(movable[getter]()).toBe(movable.state[getter]);
|
|
58
|
+
},
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
it("sets default state when constructed", () => {
|
|
62
|
+
const dummyGraphie: any = {};
|
|
63
|
+
const movable = new Movable(dummyGraphie, {});
|
|
64
|
+
expect(movable.state).toEqual({
|
|
65
|
+
id: expect.any(String),
|
|
66
|
+
add: [],
|
|
67
|
+
added: true,
|
|
68
|
+
cursor: null,
|
|
69
|
+
draw: [],
|
|
70
|
+
isDragging: false,
|
|
71
|
+
isHovering: false,
|
|
72
|
+
isMouseOver: false,
|
|
73
|
+
modify: [],
|
|
74
|
+
mouseTarget: null,
|
|
75
|
+
onClick: [],
|
|
76
|
+
onMove: [],
|
|
77
|
+
onMoveEnd: [],
|
|
78
|
+
onMoveStart: [],
|
|
79
|
+
remove: [],
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("calls the modify listener when constructed", () => {
|
|
84
|
+
const dummyGraphie: any = {};
|
|
85
|
+
const modifySpy = jest.fn().mockName("modify");
|
|
86
|
+
|
|
87
|
+
const _ = new Movable(dummyGraphie, {modify: modifySpy});
|
|
88
|
+
|
|
89
|
+
const baseExpectedState = {
|
|
90
|
+
add: [],
|
|
91
|
+
added: false,
|
|
92
|
+
cursor: null,
|
|
93
|
+
draw: [],
|
|
94
|
+
id: expect.any(String),
|
|
95
|
+
isDragging: false,
|
|
96
|
+
isHovering: false,
|
|
97
|
+
isMouseOver: false,
|
|
98
|
+
modify: [modifySpy],
|
|
99
|
+
mouseTarget: null,
|
|
100
|
+
onClick: [],
|
|
101
|
+
onMove: [],
|
|
102
|
+
onMoveEnd: [],
|
|
103
|
+
onMoveStart: [],
|
|
104
|
+
remove: [],
|
|
105
|
+
};
|
|
106
|
+
expect(modifySpy.mock.calls).toEqual([
|
|
107
|
+
[baseExpectedState, {}],
|
|
108
|
+
[
|
|
109
|
+
{...baseExpectedState, added: true},
|
|
110
|
+
{...baseExpectedState, added: true},
|
|
111
|
+
],
|
|
112
|
+
]);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("cloneState()", () => {
|
|
116
|
+
const movable = new Movable(
|
|
117
|
+
new Graphie(document.createElement("div")),
|
|
118
|
+
{},
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
expect(movable.cloneState()).toEqual(
|
|
122
|
+
expect.objectContaining({
|
|
123
|
+
id: expect.any(String),
|
|
124
|
+
add: [],
|
|
125
|
+
added: true,
|
|
126
|
+
cursor: null,
|
|
127
|
+
draw: [],
|
|
128
|
+
isDragging: false,
|
|
129
|
+
isHovering: false,
|
|
130
|
+
isMouseOver: false,
|
|
131
|
+
modify: [],
|
|
132
|
+
mouseTarget: null,
|
|
133
|
+
onClick: [],
|
|
134
|
+
onMove: [],
|
|
135
|
+
onMoveEnd: [],
|
|
136
|
+
onMoveStart: [],
|
|
137
|
+
remove: [],
|
|
138
|
+
}),
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("cloneState() makes a copy", () => {
|
|
143
|
+
const movable = new Movable(
|
|
144
|
+
new Graphie(document.createElement("div")),
|
|
145
|
+
{},
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
expect(movable.cloneState()).not.toBe(movable.state);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("modify() retains original ID", () => {
|
|
152
|
+
const movable = new Movable(
|
|
153
|
+
new Graphie(document.createElement("div")),
|
|
154
|
+
{},
|
|
155
|
+
);
|
|
156
|
+
const id = movable.state.id;
|
|
157
|
+
|
|
158
|
+
movable.modify({added: true});
|
|
159
|
+
|
|
160
|
+
expect(movable.state.id).toBe(id);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("grab() fires onMoveStart", () => {
|
|
164
|
+
const graphie = new Graphie(document.createElement("div"));
|
|
165
|
+
graphie.init({
|
|
166
|
+
range: [
|
|
167
|
+
[-10, 10],
|
|
168
|
+
[-10, 10],
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
const onMoveStart = jest.fn();
|
|
172
|
+
const movable = new Movable(graphie, {onMoveStart});
|
|
173
|
+
|
|
174
|
+
movable.grab([0, 0]);
|
|
175
|
+
|
|
176
|
+
expect(onMoveStart).toHaveBeenCalledWith([0, 0], [0, 0]);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("grab() fires onMove when mouse moves", () => {
|
|
180
|
+
const graphie = new Graphie(document.createElement("div"));
|
|
181
|
+
graphie.init({
|
|
182
|
+
range: [
|
|
183
|
+
[-10, 10],
|
|
184
|
+
[-10, 10],
|
|
185
|
+
],
|
|
186
|
+
scale: [10, 10],
|
|
187
|
+
});
|
|
188
|
+
const onMove = jest.fn();
|
|
189
|
+
const movable = new Movable(graphie, {onMove});
|
|
190
|
+
|
|
191
|
+
movable.grab([0, 0]);
|
|
192
|
+
// eslint-disable-next-line testing-library/prefer-user-event
|
|
193
|
+
fireEvent.mouseMove(document, {clientX: 120, clientY: 80});
|
|
194
|
+
|
|
195
|
+
expect(onMove).toHaveBeenCalledWith([2, 2], [0, 0]);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("grab() fires onMoveEnd when mouse up", () => {
|
|
199
|
+
const dummyGraphie: any = {};
|
|
200
|
+
const onMoveEnd = jest.fn();
|
|
201
|
+
const movable = new Movable(dummyGraphie, {onMoveEnd});
|
|
202
|
+
|
|
203
|
+
movable.grab([0, 0]);
|
|
204
|
+
// eslint-disable-next-line testing-library/prefer-user-event
|
|
205
|
+
fireEvent.mouseUp(document);
|
|
206
|
+
|
|
207
|
+
expect(onMoveEnd).toHaveBeenCalledWith([0, 0], [0, 0]);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("grab() fires onClick if still hovering when mouse up", () => {
|
|
211
|
+
const dummyGraphie: any = {};
|
|
212
|
+
const onClick = jest.fn();
|
|
213
|
+
const movable = new Movable(dummyGraphie, {onClick});
|
|
214
|
+
|
|
215
|
+
movable.grab([0, 0]);
|
|
216
|
+
// eslint-disable-next-line testing-library/prefer-user-event
|
|
217
|
+
fireEvent.mouseUp(document);
|
|
218
|
+
|
|
219
|
+
expect(onClick).toHaveBeenCalledWith([0, 0], [0, 0]);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test("draw() fires a draw event", () => {
|
|
223
|
+
const dummyGraphie: any = {};
|
|
224
|
+
const drawSpy = jest.fn();
|
|
225
|
+
const movable = new Movable(dummyGraphie, {draw: drawSpy});
|
|
226
|
+
|
|
227
|
+
movable.draw();
|
|
228
|
+
|
|
229
|
+
const expectedState = {
|
|
230
|
+
add: [],
|
|
231
|
+
added: true,
|
|
232
|
+
cursor: null,
|
|
233
|
+
draw: [drawSpy],
|
|
234
|
+
id: expect.any(String),
|
|
235
|
+
isDragging: false,
|
|
236
|
+
isHovering: false,
|
|
237
|
+
isMouseOver: false,
|
|
238
|
+
modify: [],
|
|
239
|
+
mouseTarget: null,
|
|
240
|
+
onClick: [],
|
|
241
|
+
onMove: [],
|
|
242
|
+
onMoveEnd: [],
|
|
243
|
+
onMoveStart: [],
|
|
244
|
+
remove: [],
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
expect(drawSpy).toHaveBeenCalledWith(expectedState, expectedState);
|
|
248
|
+
});
|
|
249
|
+
});
|