@khanacademy/perseus 19.1.4 → 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 +10 -0
- package/dist/components/graphie.d.ts +9 -1
- package/dist/es/index.js +255 -122
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +261 -126
- package/dist/index.js.map +1 -1
- package/dist/interactive2/interactive-util.d.ts +1 -1
- package/dist/interactive2/movable-point-options.d.ts +5 -4
- package/dist/interactive2/movable.d.ts +90 -13
- package/dist/interactive2/types.d.ts +6 -0
- package/dist/util/graphie.d.ts +5 -0
- 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 +42 -30
- package/src/interactive2/movable-point-options.ts +31 -19
- package/src/interactive2/movable.test.ts +249 -0
- package/src/interactive2/movable.ts +289 -131
- package/src/interactive2/types.ts +15 -0
- package/src/interactive2.ts +1 -1
- package/src/util/graphie.ts +10 -0
- package/src/util/interactive.ts +4 -2
- package/tsconfig-build.tsbuildinfo +1 -1
- package/src/interactive2/__tests__/movable.test.ts +0 -157
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @khanacademy/perseus
|
|
2
2
|
|
|
3
|
+
## 19.1.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#964](https://github.com/Khan/perseus/pull/964) [`d8fbc251`](https://github.com/Khan/perseus/commit/d8fbc25170bd671ad984893553f79f44e3a0d048) Thanks [@benchristel](https://github.com/benchristel)! - Internal: Refactor Movable to be an ES6 class
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`d8fbc251`](https://github.com/Khan/perseus/commit/d8fbc25170bd671ad984893553f79f44e3a0d048), [`ba44dd40`](https://github.com/Khan/perseus/commit/ba44dd405272b066615099c8bd30033715305939)]:
|
|
10
|
+
- @khanacademy/kmath@0.1.11
|
|
11
|
+
- @khanacademy/math-input@17.0.4
|
|
12
|
+
|
|
3
13
|
## 19.1.4
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
|
@@ -32,6 +32,9 @@ type DefaultProps = {
|
|
|
32
32
|
};
|
|
33
33
|
interface Movable {
|
|
34
34
|
remove(): void;
|
|
35
|
+
props: unknown;
|
|
36
|
+
modify(graphie: GraphieDrawingContext): "reordered" | undefined;
|
|
37
|
+
toFront(): void;
|
|
35
38
|
}
|
|
36
39
|
declare class Graphie extends React.Component<Props> {
|
|
37
40
|
graphieDivRef: React.RefObject<HTMLDivElement>;
|
|
@@ -56,7 +59,12 @@ declare class Graphie extends React.Component<Props> {
|
|
|
56
59
|
_scale: () => Coord;
|
|
57
60
|
_setupGraphie: () => void;
|
|
58
61
|
_removeMovables: () => void;
|
|
59
|
-
_renderMovables: (children: ReadonlyArray<any>, arg2:
|
|
62
|
+
_renderMovables: (children: ReadonlyArray<any>, arg2: {
|
|
63
|
+
nextKey: number;
|
|
64
|
+
graphie: GraphieDrawingContext;
|
|
65
|
+
oldMovables: Record<string, Movable>;
|
|
66
|
+
newMovables: Record<string, Movable>;
|
|
67
|
+
}) => React.ReactElement;
|
|
60
68
|
_updateMovables: () => void;
|
|
61
69
|
render(): React.ReactNode;
|
|
62
70
|
}
|
package/dist/es/index.js
CHANGED
|
@@ -3975,10 +3975,10 @@ FixedToResponsive.defaultProps = {
|
|
|
3975
3975
|
|
|
3976
3976
|
/* Local helper methods. */
|
|
3977
3977
|
|
|
3978
|
-
function getKey(eventName, id) {
|
|
3978
|
+
function getKey$1(eventName, id) {
|
|
3979
3979
|
return eventName + ":" + id;
|
|
3980
3980
|
}
|
|
3981
|
-
function getEventName(key) {
|
|
3981
|
+
function getEventName$1(key) {
|
|
3982
3982
|
return key.split(":")[0];
|
|
3983
3983
|
}
|
|
3984
3984
|
const MovableHelperMethods = {
|
|
@@ -4055,7 +4055,7 @@ const MovableHelperMethods = {
|
|
|
4055
4055
|
|
|
4056
4056
|
// If there's an existing handler, replace it by using its index in
|
|
4057
4057
|
// `this.state[eventName]`; otherwise, add this handler to the end
|
|
4058
|
-
const key = getKey(eventName, id);
|
|
4058
|
+
const key = getKey$1(eventName, id);
|
|
4059
4059
|
const index = this._listenerMap[key] = this._listenerMap[key] || this.state[eventName].length;
|
|
4060
4060
|
this.state[eventName][index] = func;
|
|
4061
4061
|
},
|
|
@@ -4067,7 +4067,7 @@ const MovableHelperMethods = {
|
|
|
4067
4067
|
*/
|
|
4068
4068
|
unlisten: function (eventName, id) {
|
|
4069
4069
|
this._listenerMap = this._listenerMap || {};
|
|
4070
|
-
const key = getKey(eventName, id);
|
|
4070
|
+
const key = getKey$1(eventName, id);
|
|
4071
4071
|
const index = this._listenerMap[key];
|
|
4072
4072
|
if (index !== undefined) {
|
|
4073
4073
|
// Remove handler from list of event handlers and listenerMap
|
|
@@ -4077,7 +4077,7 @@ const MovableHelperMethods = {
|
|
|
4077
4077
|
// Re-index existing events: if they occur after `index`, decrement
|
|
4078
4078
|
const keys = _.keys(this._listenerMap);
|
|
4079
4079
|
_.each(keys, function (key) {
|
|
4080
|
-
if (getEventName(key) === eventName &&
|
|
4080
|
+
if (getEventName$1(key) === eventName &&
|
|
4081
4081
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
4082
4082
|
this._listenerMap[key] > index) {
|
|
4083
4083
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
@@ -8705,6 +8705,10 @@ class Graphie$1 {
|
|
|
8705
8705
|
// Refactor to accessor methods that look at this.dimensions.
|
|
8706
8706
|
this.xpixels = void 0;
|
|
8707
8707
|
this.ypixels = void 0;
|
|
8708
|
+
// set by Movables
|
|
8709
|
+
// TODO(benchristel): consider putting this state on the Movable instead of
|
|
8710
|
+
// on the Graphie
|
|
8711
|
+
this.isDragging = void 0;
|
|
8708
8712
|
this.label = (point, text, direction, arg4, arg5) => {
|
|
8709
8713
|
const style = typeof arg4 === "object" ? arg4 : arg5;
|
|
8710
8714
|
const latex = typeof arg4 === "boolean" ? arg4 : true;
|
|
@@ -9526,6 +9530,11 @@ class Graphie$1 {
|
|
|
9526
9530
|
});
|
|
9527
9531
|
return processed;
|
|
9528
9532
|
}
|
|
9533
|
+
|
|
9534
|
+
// This is a stub that's overridden in interactive.ts
|
|
9535
|
+
getMouseCoord(event) {
|
|
9536
|
+
throw new Error("getMouseCoord is a stub, and is not implemented");
|
|
9537
|
+
}
|
|
9529
9538
|
}
|
|
9530
9539
|
const labelDirections = {
|
|
9531
9540
|
center: [-0.5, -0.5],
|
|
@@ -13722,8 +13731,7 @@ var GraphieClasses = {
|
|
|
13722
13731
|
const normalizeOptions$3 = InteractiveUtil.normalizeOptions;
|
|
13723
13732
|
const assert$8 = InteractiveUtil.assert;
|
|
13724
13733
|
|
|
13725
|
-
// Default "props" and "state". Both are added to this.state
|
|
13726
|
-
// receive magic getter methods (this.isHovering() etc).
|
|
13734
|
+
// Default "props" and "state". Both are added to this.state.
|
|
13727
13735
|
// However, properties in DEFAULT_PROPS are updated on `modify()`,
|
|
13728
13736
|
// while those in DEFAULT_STATE persist and are not updated.
|
|
13729
13737
|
// Things that the user might want to change should be on "props",
|
|
@@ -13738,27 +13746,23 @@ const DEFAULT_STATE$3 = {
|
|
|
13738
13746
|
isDragging: false,
|
|
13739
13747
|
mouseTarget: null
|
|
13740
13748
|
};
|
|
13741
|
-
|
|
13742
|
-
|
|
13743
|
-
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13749
|
+
class Movable {
|
|
13750
|
+
constructor(graphie, options) {
|
|
13751
|
+
this.graphie = void 0;
|
|
13752
|
+
this.state = void 0;
|
|
13753
|
+
this.prevState = void 0;
|
|
13754
|
+
// TODO(benchristel): delete _listenerMap; it's unused
|
|
13755
|
+
this._listenerMap = {};
|
|
13756
|
+
this.graphie = graphie;
|
|
13757
|
+
this.state = {
|
|
13747
13758
|
id: _.uniqueId("movable")
|
|
13748
|
-
}
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
InteractiveUtil.createGettersFor(Movable, _.extend({}, DEFAULT_PROPS$3, DEFAULT_STATE$3));
|
|
13756
|
-
InteractiveUtil.addMovableHelperMethodsTo(Movable);
|
|
13757
|
-
_.extend(Movable.prototype, {
|
|
13758
|
-
cloneState: function () {
|
|
13759
|
-
return _extends({}, this.state);
|
|
13760
|
-
},
|
|
13761
|
-
_createDefaultState: function () {
|
|
13759
|
+
};
|
|
13760
|
+
this.modify(_extends({}, DEFAULT_STATE$3, options));
|
|
13761
|
+
}
|
|
13762
|
+
modify(options) {
|
|
13763
|
+
this.update(_extends({}, this._createDefaultState(), options));
|
|
13764
|
+
}
|
|
13765
|
+
_createDefaultState() {
|
|
13762
13766
|
return _extends({
|
|
13763
13767
|
id: this.state.id,
|
|
13764
13768
|
add: [],
|
|
@@ -13770,63 +13774,11 @@ _.extend(Movable.prototype, {
|
|
|
13770
13774
|
onMoveEnd: [],
|
|
13771
13775
|
onClick: []
|
|
13772
13776
|
}, DEFAULT_PROPS$3);
|
|
13773
|
-
}
|
|
13774
|
-
|
|
13775
|
-
|
|
13776
|
-
|
|
13777
|
-
|
|
13778
|
-
* Analogous to React.js's replaceProps
|
|
13779
|
-
*/
|
|
13780
|
-
modify: function (options) {
|
|
13781
|
-
this.update(_extends({}, this._createDefaultState(), options));
|
|
13782
|
-
},
|
|
13783
|
-
/**
|
|
13784
|
-
* Simulates a mouse grab event on the movable object.
|
|
13785
|
-
*/
|
|
13786
|
-
grab: function (coord) {
|
|
13787
|
-
assert$8(point.is(coord));
|
|
13788
|
-
const self = this;
|
|
13789
|
-
const graphie = self.graphie;
|
|
13790
|
-
const state = self.state;
|
|
13791
|
-
state.isHovering = true;
|
|
13792
|
-
state.isDragging = true;
|
|
13793
|
-
graphie.isDragging = true;
|
|
13794
|
-
const startMouseCoord = coord;
|
|
13795
|
-
let prevMouseCoord = startMouseCoord;
|
|
13796
|
-
self._fireEvent(state.onMoveStart, startMouseCoord, startMouseCoord);
|
|
13797
|
-
const moveHandler = function moveHandler(e) {
|
|
13798
|
-
e.preventDefault();
|
|
13799
|
-
const mouseCoord = graphie.getMouseCoord(e);
|
|
13800
|
-
self._fireEvent(state.onMove, mouseCoord, prevMouseCoord);
|
|
13801
|
-
self.draw();
|
|
13802
|
-
prevMouseCoord = mouseCoord;
|
|
13803
|
-
};
|
|
13804
|
-
const upHandler = function upHandler(e) {
|
|
13805
|
-
$(document).unbind("vmousemove", moveHandler);
|
|
13806
|
-
$(document).unbind("vmouseup", upHandler);
|
|
13807
|
-
if (state.isHovering) {
|
|
13808
|
-
self._fireEvent(state.onClick, prevMouseCoord, startMouseCoord);
|
|
13809
|
-
}
|
|
13810
|
-
state.isHovering = self.state.isMouseOver;
|
|
13811
|
-
state.isDragging = false;
|
|
13812
|
-
graphie.isDragging = false;
|
|
13813
|
-
self._fireEvent(state.onMoveEnd, prevMouseCoord, startMouseCoord);
|
|
13814
|
-
self.draw();
|
|
13815
|
-
};
|
|
13816
|
-
$(document).bind("vmousemove", moveHandler);
|
|
13817
|
-
$(document).bind("vmouseup", upHandler);
|
|
13818
|
-
},
|
|
13819
|
-
/**
|
|
13820
|
-
* Adjusts constructor parameters without changing previous settings
|
|
13821
|
-
* for any option not specified
|
|
13822
|
-
*
|
|
13823
|
-
* Analogous to React.js's setProps
|
|
13824
|
-
*/
|
|
13825
|
-
update: function (options) {
|
|
13826
|
-
const self = this;
|
|
13827
|
-
const graphie = self.graphie;
|
|
13828
|
-
const prevState = self.cloneState();
|
|
13829
|
-
const state = _.extend(self.state, normalizeOptions$3(options));
|
|
13777
|
+
}
|
|
13778
|
+
update(options) {
|
|
13779
|
+
const graphie = this.graphie;
|
|
13780
|
+
const prevState = this.cloneState();
|
|
13781
|
+
const state = Object.assign(this.state, normalizeOptions$3(options));
|
|
13830
13782
|
|
|
13831
13783
|
// the invisible shape in front of the point that gets mouse events
|
|
13832
13784
|
if (state.mouseTarget && !prevState.mouseTarget) {
|
|
@@ -13838,24 +13790,24 @@ _.extend(Movable.prototype, {
|
|
|
13838
13790
|
}
|
|
13839
13791
|
const isMouse = !("ontouchstart" in window);
|
|
13840
13792
|
if (isMouse) {
|
|
13841
|
-
$mouseTarget.on("vmouseover",
|
|
13793
|
+
$mouseTarget.on("vmouseover", () => {
|
|
13842
13794
|
state.isMouseOver = true;
|
|
13843
13795
|
if (!graphie.isDragging) {
|
|
13844
13796
|
state.isHovering = true;
|
|
13845
13797
|
}
|
|
13846
|
-
if (
|
|
13798
|
+
if (this.state.added) {
|
|
13847
13799
|
// Avoid drawing if the point has been removed
|
|
13848
|
-
|
|
13800
|
+
this.draw();
|
|
13849
13801
|
}
|
|
13850
13802
|
});
|
|
13851
|
-
$mouseTarget.on("vmouseout",
|
|
13803
|
+
$mouseTarget.on("vmouseout", () => {
|
|
13852
13804
|
state.isMouseOver = false;
|
|
13853
13805
|
if (!state.isDragging) {
|
|
13854
13806
|
state.isHovering = false;
|
|
13855
13807
|
}
|
|
13856
|
-
if (
|
|
13808
|
+
if (this.state.added) {
|
|
13857
13809
|
// Avoid drawing if the point has been removed
|
|
13858
|
-
|
|
13810
|
+
this.draw();
|
|
13859
13811
|
}
|
|
13860
13812
|
});
|
|
13861
13813
|
}
|
|
@@ -13867,13 +13819,13 @@ _.extend(Movable.prototype, {
|
|
|
13867
13819
|
}, {
|
|
13868
13820
|
passive: false
|
|
13869
13821
|
});
|
|
13870
|
-
$mouseTarget.on("vmousedown",
|
|
13822
|
+
$mouseTarget.on("vmousedown", e => {
|
|
13871
13823
|
if (e.which !== 0 && e.which !== 1) {
|
|
13872
13824
|
return;
|
|
13873
13825
|
}
|
|
13874
13826
|
e.preventDefault();
|
|
13875
13827
|
const mouseCoord = graphie.getMouseCoord(e);
|
|
13876
|
-
|
|
13828
|
+
this.grab(mouseCoord);
|
|
13877
13829
|
});
|
|
13878
13830
|
}
|
|
13879
13831
|
if (state.mouseTarget && state.cursor !== undefined) {
|
|
@@ -13890,39 +13842,212 @@ _.extend(Movable.prototype, {
|
|
|
13890
13842
|
|
|
13891
13843
|
// Trigger an add event if this hasn't been added before
|
|
13892
13844
|
if (!state.added) {
|
|
13893
|
-
|
|
13845
|
+
// TODO(benchristel): No one seems to handle the modify event. Can
|
|
13846
|
+
// we delete this?
|
|
13847
|
+
// @ts-expect-error - TS2345: Argument of type '{}' is not assignable to parameter of type 'State'.
|
|
13848
|
+
this._fireEvent(state.modify, this.cloneState(), {});
|
|
13894
13849
|
state.added = true;
|
|
13895
13850
|
|
|
13896
13851
|
// Update the state for `added` and in case the add event
|
|
13897
13852
|
// changed it
|
|
13898
|
-
|
|
13853
|
+
this.prevState = this.cloneState();
|
|
13899
13854
|
}
|
|
13900
13855
|
|
|
13901
13856
|
// Trigger a modify event
|
|
13902
|
-
|
|
13903
|
-
}
|
|
13904
|
-
|
|
13905
|
-
this.state
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13857
|
+
this._fireEvent(state.modify, this.cloneState(), this.prevState);
|
|
13858
|
+
}
|
|
13859
|
+
cloneState() {
|
|
13860
|
+
return _extends({}, this.state);
|
|
13861
|
+
}
|
|
13862
|
+
|
|
13863
|
+
/**
|
|
13864
|
+
* Fire an onSomething type event to all functions in listeners
|
|
13865
|
+
*/
|
|
13866
|
+
_fireEvent(listeners, ...args) {
|
|
13867
|
+
if (listeners == null) {
|
|
13868
|
+
return;
|
|
13911
13869
|
}
|
|
13912
|
-
|
|
13870
|
+
for (const listener of listeners) {
|
|
13871
|
+
listener.call(this, ...args);
|
|
13872
|
+
}
|
|
13873
|
+
}
|
|
13874
|
+
|
|
13875
|
+
/**
|
|
13876
|
+
* Call all draw functions, and update our prevState for the next
|
|
13877
|
+
* draw function
|
|
13878
|
+
*/
|
|
13879
|
+
draw() {
|
|
13880
|
+
const currState = this.cloneState();
|
|
13881
|
+
this._fireEvent(this.state.draw, currState, this.prevState);
|
|
13882
|
+
this.prevState = currState;
|
|
13883
|
+
}
|
|
13884
|
+
|
|
13885
|
+
/**
|
|
13886
|
+
* Simulates a mouse grab event on the movable object.
|
|
13887
|
+
*/
|
|
13888
|
+
grab(coord) {
|
|
13889
|
+
assert$8(point.is(coord));
|
|
13890
|
+
const graphie = this.graphie;
|
|
13891
|
+
const state = this.state;
|
|
13892
|
+
state.isHovering = true;
|
|
13893
|
+
state.isDragging = true;
|
|
13894
|
+
graphie.isDragging = true;
|
|
13895
|
+
const startMouseCoord = coord;
|
|
13896
|
+
let prevMouseCoord = startMouseCoord;
|
|
13897
|
+
this._fireEvent(state.onMoveStart, startMouseCoord, startMouseCoord);
|
|
13898
|
+
const moveHandler = e => {
|
|
13899
|
+
e.preventDefault();
|
|
13900
|
+
const mouseCoord = graphie.getMouseCoord(e);
|
|
13901
|
+
this._fireEvent(state.onMove, mouseCoord, prevMouseCoord);
|
|
13902
|
+
this.draw();
|
|
13903
|
+
prevMouseCoord = mouseCoord;
|
|
13904
|
+
};
|
|
13905
|
+
const upHandler = () => {
|
|
13906
|
+
$(document).unbind("vmousemove", moveHandler);
|
|
13907
|
+
$(document).unbind("vmouseup", upHandler);
|
|
13908
|
+
if (state.isHovering) {
|
|
13909
|
+
this._fireEvent(state.onClick, prevMouseCoord, startMouseCoord);
|
|
13910
|
+
}
|
|
13911
|
+
state.isHovering = this.state.isMouseOver;
|
|
13912
|
+
state.isDragging = false;
|
|
13913
|
+
graphie.isDragging = false;
|
|
13914
|
+
this._fireEvent(state.onMoveEnd, prevMouseCoord, startMouseCoord);
|
|
13915
|
+
this.draw();
|
|
13916
|
+
};
|
|
13917
|
+
$(document).bind("vmousemove", moveHandler);
|
|
13918
|
+
$(document).bind("vmouseup", upHandler);
|
|
13919
|
+
}
|
|
13920
|
+
_applyConstraints(current, previous, extraOptions) {
|
|
13921
|
+
var _this$state$constrain;
|
|
13922
|
+
let skipRemaining = false;
|
|
13923
|
+
return ((_this$state$constrain = this.state.constraints) != null ? _this$state$constrain : []).reduce((memo, constraint) => {
|
|
13924
|
+
// A move that has been cancelled won't be propagated to later
|
|
13925
|
+
// constraints calls
|
|
13926
|
+
if (memo === false) {
|
|
13927
|
+
return false;
|
|
13928
|
+
}
|
|
13929
|
+
if (skipRemaining) {
|
|
13930
|
+
return memo;
|
|
13931
|
+
}
|
|
13932
|
+
const result = constraint.call(this, memo, previous, _extends({
|
|
13933
|
+
onSkipRemaining: () => {
|
|
13934
|
+
skipRemaining = true;
|
|
13935
|
+
}
|
|
13936
|
+
}, extraOptions));
|
|
13937
|
+
if (result === false) {
|
|
13938
|
+
// Returning false cancels the move
|
|
13939
|
+
return false;
|
|
13940
|
+
}
|
|
13941
|
+
if (point.is(result, 2)) {
|
|
13942
|
+
// Returning a coord from constraints overrides the move
|
|
13943
|
+
return result;
|
|
13944
|
+
}
|
|
13945
|
+
if (result === true || result == null) {
|
|
13946
|
+
// Returning true or undefined allow the move to occur
|
|
13947
|
+
return memo;
|
|
13948
|
+
}
|
|
13949
|
+
// Anything else is an error
|
|
13950
|
+
throw new PerseusError("Constraint returned invalid result: " + result, Errors.Internal);
|
|
13951
|
+
}, current);
|
|
13952
|
+
}
|
|
13953
|
+
|
|
13913
13954
|
// Change z-order to back
|
|
13914
|
-
toBack
|
|
13955
|
+
toBack() {
|
|
13915
13956
|
if (this.state.mouseTarget) {
|
|
13916
13957
|
this.state.mouseTarget.toBack();
|
|
13917
13958
|
}
|
|
13918
|
-
}
|
|
13959
|
+
}
|
|
13960
|
+
|
|
13919
13961
|
// Change z-order to front
|
|
13920
|
-
toFront
|
|
13962
|
+
toFront() {
|
|
13921
13963
|
if (this.state.mouseTarget) {
|
|
13922
13964
|
this.state.mouseTarget.toFront();
|
|
13923
13965
|
}
|
|
13924
13966
|
}
|
|
13925
|
-
|
|
13967
|
+
|
|
13968
|
+
/**
|
|
13969
|
+
* Add a listener to any event: startMove, constraints, onMove, onMoveEnd,
|
|
13970
|
+
* etc. If a listener is already bound to the given eventName and id, then
|
|
13971
|
+
* it is overwritten by func.
|
|
13972
|
+
*
|
|
13973
|
+
* eventName: the string name of the event to listen to. one of:
|
|
13974
|
+
* "onMoveStart", "onMove", "onMoveEnd", "draw", "remove"
|
|
13975
|
+
*
|
|
13976
|
+
* id: a string id that can be used to remove this event at a later time
|
|
13977
|
+
* note: adding multiple listeners with the same id is undefined behavior
|
|
13978
|
+
*
|
|
13979
|
+
* func: the function to call when the event happens, which is called
|
|
13980
|
+
* with the event's standard parameters [usually (coord, prevCoord) or
|
|
13981
|
+
* (state, prevState)]
|
|
13982
|
+
*/
|
|
13983
|
+
listen(eventName, id, func) {
|
|
13984
|
+
this._listenerMap = this._listenerMap || {};
|
|
13985
|
+
|
|
13986
|
+
// If there's an existing handler, replace it by using its index in
|
|
13987
|
+
// `this.state[eventName]`; otherwise, add this handler to the end
|
|
13988
|
+
const key = getKey(eventName, id);
|
|
13989
|
+
const index = this._listenerMap[key] = this._listenerMap[key] || this.state[eventName].length;
|
|
13990
|
+
this.state[eventName][index] = func;
|
|
13991
|
+
}
|
|
13992
|
+
|
|
13993
|
+
/**
|
|
13994
|
+
* Remove a previously added listener, by the id specified in the
|
|
13995
|
+
* corresponding listen() call
|
|
13996
|
+
*
|
|
13997
|
+
* If the given id has not been registered already, this is a no-op
|
|
13998
|
+
*/
|
|
13999
|
+
unlisten(eventName, id) {
|
|
14000
|
+
this._listenerMap = this._listenerMap || {};
|
|
14001
|
+
const key = getKey(eventName, id);
|
|
14002
|
+
const index = this._listenerMap[key];
|
|
14003
|
+
if (index !== undefined) {
|
|
14004
|
+
// Remove handler from list of event handlers and listenerMap
|
|
14005
|
+
this.state[eventName].splice(index, 1);
|
|
14006
|
+
delete this._listenerMap[key];
|
|
14007
|
+
|
|
14008
|
+
// Re-index existing events: if they occur after `index`, decrement
|
|
14009
|
+
const keys = _.keys(this._listenerMap);
|
|
14010
|
+
keys.forEach(key => {
|
|
14011
|
+
if (getEventName(key) === eventName && this._listenerMap[key] > index) {
|
|
14012
|
+
this._listenerMap[key]--;
|
|
14013
|
+
}
|
|
14014
|
+
});
|
|
14015
|
+
}
|
|
14016
|
+
}
|
|
14017
|
+
remove() {
|
|
14018
|
+
this.state.added = false;
|
|
14019
|
+
this._fireEvent(this.state.remove);
|
|
14020
|
+
if (this.state.mouseTarget) {
|
|
14021
|
+
$(this.state.mouseTarget).off();
|
|
14022
|
+
this.state.mouseTarget.remove();
|
|
14023
|
+
this.state.mouseTarget = null;
|
|
14024
|
+
}
|
|
14025
|
+
}
|
|
14026
|
+
cursor() {
|
|
14027
|
+
return this.state.cursor;
|
|
14028
|
+
}
|
|
14029
|
+
added() {
|
|
14030
|
+
return this.state.added;
|
|
14031
|
+
}
|
|
14032
|
+
isHovering() {
|
|
14033
|
+
return this.state.isHovering;
|
|
14034
|
+
}
|
|
14035
|
+
isMouseOver() {
|
|
14036
|
+
return this.state.isMouseOver;
|
|
14037
|
+
}
|
|
14038
|
+
isDragging() {
|
|
14039
|
+
return this.state.isDragging;
|
|
14040
|
+
}
|
|
14041
|
+
mouseTarget() {
|
|
14042
|
+
return this.state.mouseTarget;
|
|
14043
|
+
}
|
|
14044
|
+
}
|
|
14045
|
+
function getKey(eventName, id) {
|
|
14046
|
+
return eventName + ":" + id;
|
|
14047
|
+
}
|
|
14048
|
+
function getEventName(key) {
|
|
14049
|
+
return key.split(":")[0];
|
|
14050
|
+
}
|
|
13926
14051
|
|
|
13927
14052
|
/* eslint-disable @babel/no-invalid-this */
|
|
13928
14053
|
/**
|
|
@@ -14764,31 +14889,39 @@ const constraints$1 = {
|
|
|
14764
14889
|
snap: function (snap) {
|
|
14765
14890
|
return function (coord) {
|
|
14766
14891
|
if (snap === null) {
|
|
14767
|
-
// NOTE(kevinb): this should probably return
|
|
14892
|
+
// TODO(benchristel), NOTE(kevinb): this should probably return
|
|
14893
|
+
// the original point
|
|
14768
14894
|
return true;
|
|
14769
14895
|
}
|
|
14770
|
-
// @ts-expect-error -
|
|
14771
|
-
|
|
14772
|
-
return point.roundTo(coord, snap);
|
|
14896
|
+
// @ts-expect-error - TS2339: Property 'snap' does not exist on type 'Graphie'.
|
|
14897
|
+
return point.roundTo(coord, snap || this.graphie.snap);
|
|
14773
14898
|
};
|
|
14774
14899
|
},
|
|
14775
|
-
bound: function (range, snap,
|
|
14776
|
-
|
|
14777
|
-
if (
|
|
14778
|
-
|
|
14900
|
+
bound: function (range, snap, optionalPaddingPx) {
|
|
14901
|
+
const paddingPx = (() => {
|
|
14902
|
+
if (optionalPaddingPx === undefined) {
|
|
14903
|
+
if (range === undefined) {
|
|
14904
|
+
return 10;
|
|
14905
|
+
} else {
|
|
14906
|
+
return 0;
|
|
14907
|
+
}
|
|
14779
14908
|
} else {
|
|
14780
|
-
|
|
14909
|
+
return optionalPaddingPx;
|
|
14781
14910
|
}
|
|
14782
|
-
}
|
|
14911
|
+
})();
|
|
14783
14912
|
return function (coord, prev, options) {
|
|
14784
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
14785
14913
|
const graphie = this.graphie;
|
|
14786
14914
|
range = range || graphie.range;
|
|
14787
14915
|
if (snap === undefined) {
|
|
14916
|
+
// @ts-expect-error - Property 'snap' does not exist on type 'Graphie'.
|
|
14788
14917
|
snap = graphie.snap;
|
|
14789
14918
|
}
|
|
14790
|
-
let lower = graphie.unscalePoint([paddingPx,
|
|
14791
|
-
|
|
14919
|
+
let lower = graphie.unscalePoint([paddingPx,
|
|
14920
|
+
// @ts-expect-error - 'graphie.ypixels' is possibly 'undefined'.
|
|
14921
|
+
graphie.ypixels - paddingPx]);
|
|
14922
|
+
let upper = graphie.unscalePoint([
|
|
14923
|
+
// @ts-expect-error - 'graphie.ypixels' is possibly 'undefined'.
|
|
14924
|
+
graphie.xpixels - paddingPx, paddingPx]);
|
|
14792
14925
|
if (snap) {
|
|
14793
14926
|
lower = point.ceilTo(lower, snap);
|
|
14794
14927
|
upper = point.floorTo(upper, snap);
|
|
@@ -41467,7 +41600,7 @@ const init = function init(options) {
|
|
|
41467
41600
|
|
|
41468
41601
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41469
41602
|
const libName = "@khanacademy/perseus";
|
|
41470
|
-
const libVersion = "19.1.
|
|
41603
|
+
const libVersion = "19.1.5";
|
|
41471
41604
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41472
41605
|
|
|
41473
41606
|
const apiVersion = {
|