@khanacademy/wonder-blocks-clickable 2.4.0 → 2.4.1

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @khanacademy/wonder-blocks-clickable
2
2
 
3
+ ## 2.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 4c682709: handleClick no longer redundantly triggers on mouseup
8
+
3
9
  ## 2.4.0
4
10
 
5
11
  ### Minor Changes
package/dist/es/index.js CHANGED
@@ -41,7 +41,6 @@ const disabledHandlers = {
41
41
  onMouseLeave: () => void 0,
42
42
  onMouseDown: () => void 0,
43
43
  onMouseUp: () => void 0,
44
- onDragStart: () => void 0,
45
44
  onTouchStart: () => void 0,
46
45
  onTouchEnd: () => void 0,
47
46
  onTouchCancel: () => void 0,
@@ -91,12 +90,7 @@ class ClickableBehavior extends React.Component {
91
90
  };
92
91
 
93
92
  this.handleMouseEnter = e => {
94
- if (e.buttons === 1) {
95
- this.dragging = true;
96
- this.setState({
97
- pressed: true
98
- });
99
- } else if (!this.waitingForClick) {
93
+ if (!this.waitingForClick) {
100
94
  this.setState({
101
95
  hovered: true
102
96
  });
@@ -105,7 +99,6 @@ class ClickableBehavior extends React.Component {
105
99
 
106
100
  this.handleMouseLeave = () => {
107
101
  if (!this.waitingForClick) {
108
- this.dragging = false;
109
102
  this.setState({
110
103
  hovered: false,
111
104
  pressed: false,
@@ -121,22 +114,12 @@ class ClickableBehavior extends React.Component {
121
114
  };
122
115
 
123
116
  this.handleMouseUp = e => {
124
- if (this.dragging) {
125
- this.dragging = false;
126
- this.handleClick(e);
127
- }
128
-
129
117
  this.setState({
130
118
  pressed: false,
131
119
  focused: false
132
120
  });
133
121
  };
134
122
 
135
- this.handleDragStart = e => {
136
- this.dragging = true;
137
- e.preventDefault();
138
- };
139
-
140
123
  this.handleTouchStart = () => {
141
124
  this.setState({
142
125
  pressed: true
@@ -226,7 +209,6 @@ class ClickableBehavior extends React.Component {
226
209
  this.state = startState;
227
210
  this.waitingForClick = false;
228
211
  this.enterClick = false;
229
- this.dragging = false;
230
212
  }
231
213
 
232
214
  navigateOrReset(shouldNavigate) {
@@ -358,7 +340,6 @@ class ClickableBehavior extends React.Component {
358
340
  onMouseLeave: this.handleMouseLeave,
359
341
  onMouseDown: this.handleMouseDown,
360
342
  onMouseUp: this.handleMouseUp,
361
- onDragStart: this.handleDragStart,
362
343
  onTouchStart: this.handleTouchStart,
363
344
  onTouchEnd: this.handleTouchEnd,
364
345
  onTouchCancel: this.handleTouchCancel,
package/dist/index.js CHANGED
@@ -158,7 +158,6 @@ const disabledHandlers = {
158
158
  onMouseLeave: () => void 0,
159
159
  onMouseDown: () => void 0,
160
160
  onMouseUp: () => void 0,
161
- onDragStart: () => void 0,
162
161
  onTouchStart: () => void 0,
163
162
  onTouchEnd: () => void 0,
164
163
  onTouchCancel: () => void 0,
@@ -197,7 +196,7 @@ const startState = {
197
196
  * 3. Keyup (spacebar/enter) -> focus state
198
197
  *
199
198
  * Warning: The event handlers returned (onClick, onMouseEnter, onMouseLeave,
200
- * onMouseDown, onMouseUp, onDragStart, onTouchStart, onTouchEnd, onTouchCancel,
199
+ * onMouseDown, onMouseUp, onTouchStart, onTouchEnd, onTouchCancel,
201
200
  * onKeyDown, onKeyUp, onFocus, onBlur, tabIndex) should be passed on to the
202
201
  * component that has the ClickableBehavior. You cannot override these handlers
203
202
  * without potentially breaking the functionality of ClickableBehavior.
@@ -293,13 +292,7 @@ class ClickableBehavior extends react__WEBPACK_IMPORTED_MODULE_0__["Component"]
293
292
  };
294
293
 
295
294
  this.handleMouseEnter = e => {
296
- // When the left button is pressed already, we want it to be pressed
297
- if (e.buttons === 1) {
298
- this.dragging = true;
299
- this.setState({
300
- pressed: true
301
- });
302
- } else if (!this.waitingForClick) {
295
+ if (!this.waitingForClick) {
303
296
  this.setState({
304
297
  hovered: true
305
298
  });
@@ -308,7 +301,6 @@ class ClickableBehavior extends react__WEBPACK_IMPORTED_MODULE_0__["Component"]
308
301
 
309
302
  this.handleMouseLeave = () => {
310
303
  if (!this.waitingForClick) {
311
- this.dragging = false;
312
304
  this.setState({
313
305
  hovered: false,
314
306
  pressed: false,
@@ -324,22 +316,12 @@ class ClickableBehavior extends react__WEBPACK_IMPORTED_MODULE_0__["Component"]
324
316
  };
325
317
 
326
318
  this.handleMouseUp = e => {
327
- if (this.dragging) {
328
- this.dragging = false;
329
- this.handleClick(e);
330
- }
331
-
332
319
  this.setState({
333
320
  pressed: false,
334
321
  focused: false
335
322
  });
336
323
  };
337
324
 
338
- this.handleDragStart = e => {
339
- this.dragging = true;
340
- e.preventDefault();
341
- };
342
-
343
325
  this.handleTouchStart = () => {
344
326
  this.setState({
345
327
  pressed: true
@@ -435,7 +417,6 @@ class ClickableBehavior extends react__WEBPACK_IMPORTED_MODULE_0__["Component"]
435
417
  this.state = startState;
436
418
  this.waitingForClick = false;
437
419
  this.enterClick = false;
438
- this.dragging = false;
439
420
  }
440
421
 
441
422
  navigateOrReset(shouldNavigate) {
@@ -589,7 +570,6 @@ class ClickableBehavior extends react__WEBPACK_IMPORTED_MODULE_0__["Component"]
589
570
  onMouseLeave: this.handleMouseLeave,
590
571
  onMouseDown: this.handleMouseDown,
591
572
  onMouseUp: this.handleMouseUp,
592
- onDragStart: this.handleDragStart,
593
573
  onTouchStart: this.handleTouchStart,
594
574
  onTouchEnd: this.handleTouchEnd,
595
575
  onTouchCancel: this.handleTouchCancel,
@@ -1136,19 +1116,16 @@ function _extends() {
1136
1116
  module.exports = _extends = Object.assign ? Object.assign.bind() : function (target) {
1137
1117
  for (var i = 1; i < arguments.length; i++) {
1138
1118
  var source = arguments[i];
1139
-
1140
1119
  for (var key in source) {
1141
1120
  if (Object.prototype.hasOwnProperty.call(source, key)) {
1142
1121
  target[key] = source[key];
1143
1122
  }
1144
1123
  }
1145
1124
  }
1146
-
1147
1125
  return target;
1148
1126
  }, module.exports.__esModule = true, module.exports["default"] = module.exports;
1149
1127
  return _extends.apply(this, arguments);
1150
1128
  }
1151
-
1152
1129
  module.exports = _extends, module.exports.__esModule = true, module.exports["default"] = module.exports;
1153
1130
 
1154
1131
  /***/ }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-clickable",
3
- "version": "2.4.0",
3
+ "version": "2.4.1",
4
4
  "design": "v1",
5
5
  "description": "Clickable component for Wonder-Blocks.",
6
6
  "main": "dist/index.js",
@@ -66,6 +66,13 @@ export const Default: StoryComponentType = (args) => (
66
66
  </Clickable>
67
67
  );
68
68
 
69
+ Default.args = {
70
+ onClick: () => {
71
+ // eslint-disable-next-line no-alert
72
+ alert("Click!");
73
+ },
74
+ };
75
+
69
76
  export const Basic: StoryComponentType = () => (
70
77
  <View style={styles.centerText}>
71
78
  <Clickable
@@ -64,7 +64,7 @@ describe("ClickableBehavior", () => {
64
64
  expect(onClick).toHaveBeenCalled();
65
65
  });
66
66
 
67
- it("changes only hovered state on mouse enter/leave", () => {
67
+ it("changes hovered state on mouse enter/leave", () => {
68
68
  const onClick = jest.fn();
69
69
  render(
70
70
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
@@ -82,7 +82,7 @@ describe("ClickableBehavior", () => {
82
82
  expect(button).not.toHaveTextContent("hovered");
83
83
  });
84
84
 
85
- it("changes only pressed state on mouse enter/leave while dragging", () => {
85
+ it("changes hovered state on mouse enter while dragging", () => {
86
86
  const onClick = jest.fn();
87
87
  render(
88
88
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
@@ -93,18 +93,34 @@ describe("ClickableBehavior", () => {
93
93
  </ClickableBehavior>,
94
94
  );
95
95
  const button = screen.getByRole("button");
96
+ expect(button).not.toHaveTextContent("hovered");
97
+ expect(button).not.toHaveTextContent("pressed");
98
+
99
+ fireEvent.mouseEnter(button, {buttons: 1});
100
+ expect(button).not.toHaveTextContent("pressed");
101
+ expect(button).toHaveTextContent("hovered");
102
+ });
103
+
104
+ it("changes pressed and hover states on mouse leave while dragging", () => {
105
+ const onClick = jest.fn();
106
+ render(
107
+ <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
108
+ {(state, childrenProps) => {
109
+ const label = labelForState(state);
110
+ return <button {...childrenProps}>{label}</button>;
111
+ }}
112
+ </ClickableBehavior>,
113
+ );
114
+ const button = screen.getByRole("button");
115
+ expect(button).not.toHaveTextContent("hovered");
96
116
  expect(button).not.toHaveTextContent("pressed");
97
117
 
98
118
  fireEvent.mouseDown(button);
99
- fireEvent.dragStart(button);
100
- fireEvent.mouseMove(button);
101
119
  expect(button).toHaveTextContent("pressed");
102
120
 
103
121
  fireEvent.mouseLeave(button);
122
+ expect(button).not.toHaveTextContent("hovered");
104
123
  expect(button).not.toHaveTextContent("pressed");
105
-
106
- fireEvent.mouseEnter(button, {buttons: 1});
107
- expect(button).toHaveTextContent("pressed");
108
124
  });
109
125
 
110
126
  it("changes pressed state on mouse down/up", () => {
@@ -763,7 +779,17 @@ describe("ClickableBehavior", () => {
763
779
  expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
764
780
  });
765
781
 
766
- it("calls onClick on mouseup when the mouse was dragging", () => {
782
+ // The following two tests involve click behavior when dragging.
783
+ // Here are some notable related actions that cannot be tested using
784
+ // existing jest/RTL events since these click types are handled
785
+ // by browsers but aren't registered as clicks by RTL/jest:
786
+ // 1. Mousedown in the button, drag within the button, and mouseup
787
+ // in the button (mouse doesn't leave the button at any point).
788
+ // This should result in a successful click.
789
+ // 2. Mouse down in the button, drag out of the button (don't let go),
790
+ // drag back into the button, and mouseup inside the button.
791
+ // This should result in a successful click.
792
+ it("does not call onClick on mouseup when the mouse presses inside and drags away", () => {
767
793
  const onClick = jest.fn();
768
794
  render(
769
795
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
@@ -775,19 +801,25 @@ describe("ClickableBehavior", () => {
775
801
 
776
802
  const button = screen.getByRole("button");
777
803
  fireEvent.mouseDown(button);
778
- fireEvent.dragStart(button);
779
804
  fireEvent.mouseLeave(button);
780
805
  fireEvent.mouseUp(button);
781
806
  expect(onClick).toHaveBeenCalledTimes(0);
807
+ });
782
808
 
783
- fireEvent.mouseDown(button);
784
- fireEvent.dragStart(button);
785
- fireEvent.mouseUp(button);
786
- expect(onClick).toHaveBeenCalledTimes(1);
809
+ it("does not call onClick on mouseup when the mouse presses outside and drags in", () => {
810
+ const onClick = jest.fn();
811
+ render(
812
+ <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
813
+ {(state, childrenProps) => {
814
+ return <button {...childrenProps}>Label</button>;
815
+ }}
816
+ </ClickableBehavior>,
817
+ );
787
818
 
819
+ const button = screen.getByRole("button");
788
820
  fireEvent.mouseEnter(button, {buttons: 1});
789
821
  fireEvent.mouseUp(button);
790
- expect(onClick).toHaveBeenCalledTimes(2);
822
+ expect(onClick).toHaveBeenCalledTimes(0);
791
823
  });
792
824
 
793
825
  it("doesn't trigger enter key when browser doesn't stop the click", () => {
@@ -205,7 +205,6 @@ export type ChildrenProps = {|
205
205
  onMouseLeave: () => mixed,
206
206
  onMouseDown: () => mixed,
207
207
  onMouseUp: (e: SyntheticMouseEvent<>) => mixed,
208
- onDragStart: (e: SyntheticMouseEvent<>) => mixed,
209
208
  onTouchStart: () => mixed,
210
209
  onTouchEnd: () => mixed,
211
210
  onTouchCancel: () => mixed,
@@ -223,7 +222,6 @@ const disabledHandlers = {
223
222
  onMouseLeave: () => void 0,
224
223
  onMouseDown: () => void 0,
225
224
  onMouseUp: () => void 0,
226
- onDragStart: () => void 0,
227
225
  onTouchStart: () => void 0,
228
226
  onTouchEnd: () => void 0,
229
227
  onTouchCancel: () => void 0,
@@ -265,7 +263,7 @@ const startState: ClickableState = {
265
263
  * 3. Keyup (spacebar/enter) -> focus state
266
264
  *
267
265
  * Warning: The event handlers returned (onClick, onMouseEnter, onMouseLeave,
268
- * onMouseDown, onMouseUp, onDragStart, onTouchStart, onTouchEnd, onTouchCancel,
266
+ * onMouseDown, onMouseUp, onTouchStart, onTouchEnd, onTouchCancel,
269
267
  * onKeyDown, onKeyUp, onFocus, onBlur, tabIndex) should be passed on to the
270
268
  * component that has the ClickableBehavior. You cannot override these handlers
271
269
  * without potentially breaking the functionality of ClickableBehavior.
@@ -330,7 +328,6 @@ export default class ClickableBehavior extends React.Component<
330
328
  > {
331
329
  waitingForClick: boolean;
332
330
  enterClick: boolean;
333
- dragging: boolean;
334
331
 
335
332
  static defaultProps: DefaultProps = {
336
333
  disabled: false,
@@ -356,7 +353,6 @@ export default class ClickableBehavior extends React.Component<
356
353
  this.state = startState;
357
354
  this.waitingForClick = false;
358
355
  this.enterClick = false;
359
- this.dragging = false;
360
356
  }
361
357
 
362
358
  navigateOrReset(shouldNavigate: boolean) {
@@ -513,18 +509,13 @@ export default class ClickableBehavior extends React.Component<
513
509
  };
514
510
 
515
511
  handleMouseEnter: (e: SyntheticMouseEvent<>) => void = (e) => {
516
- // When the left button is pressed already, we want it to be pressed
517
- if (e.buttons === 1) {
518
- this.dragging = true;
519
- this.setState({pressed: true});
520
- } else if (!this.waitingForClick) {
512
+ if (!this.waitingForClick) {
521
513
  this.setState({hovered: true});
522
514
  }
523
515
  };
524
516
 
525
517
  handleMouseLeave: () => void = () => {
526
518
  if (!this.waitingForClick) {
527
- this.dragging = false;
528
519
  this.setState({hovered: false, pressed: false, focused: false});
529
520
  }
530
521
  };
@@ -534,18 +525,9 @@ export default class ClickableBehavior extends React.Component<
534
525
  };
535
526
 
536
527
  handleMouseUp: (e: SyntheticMouseEvent<>) => void = (e) => {
537
- if (this.dragging) {
538
- this.dragging = false;
539
- this.handleClick(e);
540
- }
541
528
  this.setState({pressed: false, focused: false});
542
529
  };
543
530
 
544
- handleDragStart: (e: SyntheticMouseEvent<>) => void = (e) => {
545
- this.dragging = true;
546
- e.preventDefault();
547
- };
548
-
549
531
  handleTouchStart: () => void = () => {
550
532
  this.setState({pressed: true});
551
533
  };
@@ -630,7 +612,6 @@ export default class ClickableBehavior extends React.Component<
630
612
  onMouseLeave: this.handleMouseLeave,
631
613
  onMouseDown: this.handleMouseDown,
632
614
  onMouseUp: this.handleMouseUp,
633
- onDragStart: this.handleDragStart,
634
615
  onTouchStart: this.handleTouchStart,
635
616
  onTouchEnd: this.handleTouchEnd,
636
617
  onTouchCancel: this.handleTouchCancel,