@khanacademy/wonder-blocks-popover 1.1.2 → 1.1.6
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 +9 -0
- package/dist/es/index.js +59 -58
- package/package.json +15 -16
- package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +8 -8
- package/src/components/__tests__/focus-manager.test.js +29 -3
- package/src/components/__tests__/initial-focus.test.js +0 -2
- package/src/components/__tests__/popover-anchor.test.js +1 -0
- package/src/components/__tests__/popover-content.test.js +1 -0
- package/src/components/__tests__/popover-dialog.test.js +1 -0
- package/src/components/__tests__/popover-event-listener.test.js +1 -0
- package/src/components/__tests__/popover.test.js +1 -0
- package/src/components/popover.js +2 -3
- package/src/components/popover.stories.js +9 -2
- package/LICENSE +0 -21
package/CHANGELOG.md
ADDED
package/dist/es/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _extends from '@babel/runtime/helpers/extends';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as ReactDOM from 'react-dom';
|
|
4
|
+
import ReactDOM__default from 'react-dom';
|
|
4
5
|
import { View, IDProvider, addStyle } from '@khanacademy/wonder-blocks-core';
|
|
5
6
|
import { TooltipTail, TooltipPopper } from '@khanacademy/wonder-blocks-tooltip';
|
|
6
7
|
import { maybeGetPortalMountedModalHostElement } from '@khanacademy/wonder-blocks-modal';
|
|
@@ -26,15 +27,15 @@ const defaultContext = {
|
|
|
26
27
|
* of the following values: "top", "bottom", "left" or "right".
|
|
27
28
|
*/
|
|
28
29
|
|
|
29
|
-
var PopoverContext = /*#__PURE__*/createContext(defaultContext);
|
|
30
|
+
var PopoverContext = /*#__PURE__*/React.createContext(defaultContext);
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* The element that triggers the popover dialog. This is also used as reference
|
|
33
34
|
* to position the dialog itself.
|
|
34
35
|
*/
|
|
35
|
-
class PopoverAnchor extends Component {
|
|
36
|
+
class PopoverAnchor extends React.Component {
|
|
36
37
|
componentDidMount() {
|
|
37
|
-
const anchorNode = findDOMNode(this);
|
|
38
|
+
const anchorNode = ReactDOM.findDOMNode(this);
|
|
38
39
|
|
|
39
40
|
if (anchorNode) {
|
|
40
41
|
this.props.anchorRef(anchorNode);
|
|
@@ -61,11 +62,11 @@ class PopoverAnchor extends Component {
|
|
|
61
62
|
open: onClick
|
|
62
63
|
}); // we clone it to allow injecting the sharedProps defined before
|
|
63
64
|
|
|
64
|
-
return /*#__PURE__*/cloneElement(renderedChildren, sharedProps);
|
|
65
|
+
return /*#__PURE__*/React.cloneElement(renderedChildren, sharedProps);
|
|
65
66
|
} else {
|
|
66
67
|
// add onClick handler to automatically open the dialog after
|
|
67
68
|
// clicking on this anchor element
|
|
68
|
-
return /*#__PURE__*/cloneElement(children, _extends({}, children.props, sharedProps, {
|
|
69
|
+
return /*#__PURE__*/React.cloneElement(children, _extends({}, children.props, sharedProps, {
|
|
69
70
|
onClick: children.props.onClick ? e => {
|
|
70
71
|
e.stopPropagation(); // This is done to avoid overriding a custom onClick
|
|
71
72
|
// handler inside the children node
|
|
@@ -93,7 +94,7 @@ class PopoverAnchor extends Component {
|
|
|
93
94
|
*
|
|
94
95
|
* Note that without explicit positioning, the tail will not be centered.
|
|
95
96
|
*/
|
|
96
|
-
class PopoverDialog extends Component {
|
|
97
|
+
class PopoverDialog extends React.Component {
|
|
97
98
|
componentDidUpdate(prevProps) {
|
|
98
99
|
// if the placement has changed, then we need to notify this to the
|
|
99
100
|
// parent component (`Popover`). This way, the context will update its
|
|
@@ -118,14 +119,14 @@ class PopoverDialog extends Component {
|
|
|
118
119
|
const contentProps = children.props; // extract the background color from the popover content
|
|
119
120
|
|
|
120
121
|
const color = contentProps.emphasized ? "blue" : contentProps.color;
|
|
121
|
-
return /*#__PURE__*/createElement(Fragment, null, /*#__PURE__*/createElement(View, {
|
|
122
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
122
123
|
"aria-describedby": ariaDescribedby,
|
|
123
124
|
id: id,
|
|
124
125
|
role: "dialog",
|
|
125
126
|
ref: updateBubbleRef,
|
|
126
127
|
"data-placement": placement,
|
|
127
|
-
style: [isReferenceHidden && styles.hide, styles[`content-${placement}`], style]
|
|
128
|
-
}, children, /*#__PURE__*/createElement(TooltipTail, {
|
|
128
|
+
style: [isReferenceHidden && styles$2.hide, styles$2[`content-${placement}`], style]
|
|
129
|
+
}, children, /*#__PURE__*/React.createElement(TooltipTail, {
|
|
129
130
|
color: color,
|
|
130
131
|
updateRef: updateTailRef,
|
|
131
132
|
placement: placement,
|
|
@@ -134,7 +135,7 @@ class PopoverDialog extends Component {
|
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
}
|
|
137
|
-
const styles = StyleSheet.create({
|
|
138
|
+
const styles$2 = StyleSheet.create({
|
|
138
139
|
/**
|
|
139
140
|
* The hide style ensures that the bounds of the popover stay unchanged.
|
|
140
141
|
* This is because popper.js calculates the bubble position based off its
|
|
@@ -178,7 +179,7 @@ function findFocusableNodes(root) {
|
|
|
178
179
|
* This component finds which element (from within the children) needs to
|
|
179
180
|
* receive focus. After that, the children is rendered with the focus assigned.
|
|
180
181
|
*/
|
|
181
|
-
class InitialFocus extends Component {
|
|
182
|
+
class InitialFocus extends React.Component {
|
|
182
183
|
constructor(...args) {
|
|
183
184
|
super(...args);
|
|
184
185
|
|
|
@@ -201,7 +202,7 @@ class InitialFocus extends Component {
|
|
|
201
202
|
}
|
|
202
203
|
|
|
203
204
|
componentDidMount() {
|
|
204
|
-
const node = findDOMNode(this);
|
|
205
|
+
const node = ReactDOM.findDOMNode(this);
|
|
205
206
|
|
|
206
207
|
if (!node) {
|
|
207
208
|
return;
|
|
@@ -269,7 +270,7 @@ class InitialFocus extends Component {
|
|
|
269
270
|
* next shift + tab will set focus on the PopoverAnchor element.
|
|
270
271
|
*
|
|
271
272
|
*/
|
|
272
|
-
class FocusManager extends Component {
|
|
273
|
+
class FocusManager extends React.Component {
|
|
273
274
|
constructor(...args) {
|
|
274
275
|
super(...args);
|
|
275
276
|
this.focusableElementsInPopover = [];
|
|
@@ -321,7 +322,7 @@ class FocusManager extends Component {
|
|
|
321
322
|
return;
|
|
322
323
|
}
|
|
323
324
|
|
|
324
|
-
const rootNode = findDOMNode(node);
|
|
325
|
+
const rootNode = ReactDOM.findDOMNode(node);
|
|
325
326
|
|
|
326
327
|
if (!rootNode) {
|
|
327
328
|
throw new Error("Assertion error: root node should exist after mount");
|
|
@@ -405,17 +406,17 @@ class FocusManager extends Component {
|
|
|
405
406
|
const {
|
|
406
407
|
children
|
|
407
408
|
} = this.props;
|
|
408
|
-
return /*#__PURE__*/createElement(Fragment, null, /*#__PURE__*/createElement("div", {
|
|
409
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
409
410
|
tabIndex: "0",
|
|
410
411
|
onFocus: this.handleFocusPreviousFocusableElement,
|
|
411
412
|
style: {
|
|
412
413
|
position: "fixed"
|
|
413
414
|
}
|
|
414
|
-
}), /*#__PURE__*/createElement("div", {
|
|
415
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
415
416
|
ref: this.getComponentRootNode
|
|
416
|
-
}, /*#__PURE__*/createElement(InitialFocus, {
|
|
417
|
+
}, /*#__PURE__*/React.createElement(InitialFocus, {
|
|
417
418
|
initialFocusId: this.props.initialFocusId
|
|
418
|
-
}, children)), /*#__PURE__*/createElement("div", {
|
|
419
|
+
}, children)), /*#__PURE__*/React.createElement("div", {
|
|
419
420
|
tabIndex: "0",
|
|
420
421
|
onFocus: this.handleFocusNextFocusableElement,
|
|
421
422
|
style: {
|
|
@@ -431,7 +432,7 @@ class FocusManager extends Component {
|
|
|
431
432
|
* This includes when pressing Escape or clicking outside the Popover.
|
|
432
433
|
* @see @khanacademy/wonder-blocks-modal/components/modal-launcher.js
|
|
433
434
|
*/
|
|
434
|
-
class PopoverEventListener extends Component {
|
|
435
|
+
class PopoverEventListener extends React.Component {
|
|
435
436
|
constructor(...args) {
|
|
436
437
|
super(...args);
|
|
437
438
|
this.state = {
|
|
@@ -467,7 +468,7 @@ class PopoverEventListener extends Component {
|
|
|
467
468
|
return;
|
|
468
469
|
}
|
|
469
470
|
|
|
470
|
-
const node =
|
|
471
|
+
const node = ReactDOM__default.findDOMNode((_this$props$contentRe = this.props.contentRef) == null ? void 0 : _this$props$contentRe.current);
|
|
471
472
|
|
|
472
473
|
if (node && !node.contains(e.target)) {
|
|
473
474
|
// Stop the event going any further.
|
|
@@ -504,7 +505,7 @@ class PopoverEventListener extends Component {
|
|
|
504
505
|
* This component uses the `PopoverPopper` component to position the
|
|
505
506
|
* `PopoverContentCore` component according to the children it is wrapping.
|
|
506
507
|
*/
|
|
507
|
-
class Popover extends Component {
|
|
508
|
+
class Popover extends React.Component {
|
|
508
509
|
constructor(...args) {
|
|
509
510
|
super(...args);
|
|
510
511
|
this.state = {
|
|
@@ -512,7 +513,7 @@ class Popover extends Component {
|
|
|
512
513
|
anchorElement: null,
|
|
513
514
|
placement: this.props.placement
|
|
514
515
|
};
|
|
515
|
-
this.contentRef = /*#__PURE__*/createRef();
|
|
516
|
+
this.contentRef = /*#__PURE__*/React.createRef();
|
|
516
517
|
|
|
517
518
|
this.handleClose = () => {
|
|
518
519
|
this.setState({
|
|
@@ -535,7 +536,7 @@ class Popover extends Component {
|
|
|
535
536
|
};
|
|
536
537
|
|
|
537
538
|
this.updateRef = ref => {
|
|
538
|
-
const actualRef = ref &&
|
|
539
|
+
const actualRef = ref && ReactDOM__default.findDOMNode(ref);
|
|
539
540
|
|
|
540
541
|
if (actualRef && this.state.anchorElement !== actualRef) {
|
|
541
542
|
this.setState({
|
|
@@ -559,7 +560,7 @@ class Popover extends Component {
|
|
|
559
560
|
const {
|
|
560
561
|
content
|
|
561
562
|
} = this.props;
|
|
562
|
-
return /*#__PURE__*/cloneElement(typeof content === "function" ? content({
|
|
563
|
+
return /*#__PURE__*/React.cloneElement(typeof content === "function" ? content({
|
|
563
564
|
close: this.handleClose
|
|
564
565
|
}) : content, {
|
|
565
566
|
ref: this.contentRef
|
|
@@ -574,13 +575,13 @@ class Popover extends Component {
|
|
|
574
575
|
const {
|
|
575
576
|
anchorElement
|
|
576
577
|
} = this.state;
|
|
577
|
-
return /*#__PURE__*/createElement(FocusManager, {
|
|
578
|
+
return /*#__PURE__*/React.createElement(FocusManager, {
|
|
578
579
|
anchorElement: anchorElement,
|
|
579
580
|
initialFocusId: initialFocusId
|
|
580
|
-
}, /*#__PURE__*/createElement(TooltipPopper, {
|
|
581
|
+
}, /*#__PURE__*/React.createElement(TooltipPopper, {
|
|
581
582
|
anchorElement: anchorElement,
|
|
582
583
|
placement: placement
|
|
583
|
-
}, props => /*#__PURE__*/createElement(PopoverDialog, _extends({}, props, {
|
|
584
|
+
}, props => /*#__PURE__*/React.createElement(PopoverDialog, _extends({}, props, {
|
|
584
585
|
"aria-describedby": `${uniqueId}-anchor`,
|
|
585
586
|
id: uniqueId,
|
|
586
587
|
onUpdate: placement => this.setState({
|
|
@@ -608,21 +609,21 @@ class Popover extends Component {
|
|
|
608
609
|
placement
|
|
609
610
|
} = this.state;
|
|
610
611
|
const popperHost = this.getHost();
|
|
611
|
-
return /*#__PURE__*/createElement(PopoverContext.Provider, {
|
|
612
|
+
return /*#__PURE__*/React.createElement(PopoverContext.Provider, {
|
|
612
613
|
value: {
|
|
613
614
|
close: this.handleClose,
|
|
614
615
|
placement: placement
|
|
615
616
|
}
|
|
616
|
-
}, /*#__PURE__*/createElement(IDProvider, {
|
|
617
|
+
}, /*#__PURE__*/React.createElement(IDProvider, {
|
|
617
618
|
id: id,
|
|
618
619
|
scope: "popover"
|
|
619
|
-
}, uniqueId => /*#__PURE__*/createElement(Fragment, null, /*#__PURE__*/createElement(PopoverAnchor, {
|
|
620
|
+
}, uniqueId => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(PopoverAnchor, {
|
|
620
621
|
anchorRef: this.updateRef,
|
|
621
622
|
id: `${uniqueId}-anchor`,
|
|
622
623
|
"aria-controls": uniqueId,
|
|
623
624
|
"aria-expanded": opened ? "true" : "false",
|
|
624
625
|
onClick: this.handleOpen
|
|
625
|
-
}, children), popperHost && opened && /*#__PURE__*/
|
|
626
|
+
}, children), popperHost && opened && /*#__PURE__*/ReactDOM__default.createPortal(this.renderPopper(uniqueId), popperHost))), dismissEnabled && opened && /*#__PURE__*/React.createElement(PopoverEventListener, {
|
|
626
627
|
onClose: this.handleClose,
|
|
627
628
|
contentRef: this.contentRef
|
|
628
629
|
}));
|
|
@@ -638,7 +639,7 @@ Popover.defaultProps = {
|
|
|
638
639
|
* inside the PopoverContentCore. It’s rendered if closeButtonVisible is set
|
|
639
640
|
* true.
|
|
640
641
|
*/
|
|
641
|
-
class CloseButton extends Component {
|
|
642
|
+
class CloseButton extends React.Component {
|
|
642
643
|
render() {
|
|
643
644
|
const {
|
|
644
645
|
light,
|
|
@@ -646,10 +647,10 @@ class CloseButton extends Component {
|
|
|
646
647
|
style,
|
|
647
648
|
testId
|
|
648
649
|
} = this.props;
|
|
649
|
-
return /*#__PURE__*/createElement(PopoverContext.Consumer, null, ({
|
|
650
|
+
return /*#__PURE__*/React.createElement(PopoverContext.Consumer, null, ({
|
|
650
651
|
close
|
|
651
652
|
}) => {
|
|
652
|
-
return /*#__PURE__*/createElement(IconButton, {
|
|
653
|
+
return /*#__PURE__*/React.createElement(IconButton, {
|
|
653
654
|
icon: icons.dismiss,
|
|
654
655
|
"aria-label": ariaLabel,
|
|
655
656
|
onClick: close,
|
|
@@ -671,7 +672,7 @@ CloseButton.defaultProps = {
|
|
|
671
672
|
* This is the base popover container. It’s used internally by all the variants.
|
|
672
673
|
* Also, it can be used to create flexible popovers.
|
|
673
674
|
*/
|
|
674
|
-
class PopoverContentCore extends Component {
|
|
675
|
+
class PopoverContentCore extends React.Component {
|
|
675
676
|
render() {
|
|
676
677
|
const {
|
|
677
678
|
children,
|
|
@@ -682,10 +683,10 @@ class PopoverContentCore extends Component {
|
|
|
682
683
|
style,
|
|
683
684
|
testId
|
|
684
685
|
} = this.props;
|
|
685
|
-
return /*#__PURE__*/createElement(View, {
|
|
686
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
686
687
|
"data-test-id": testId,
|
|
687
688
|
style: [styles$1.content, color !== "white" && styles$1[color], style]
|
|
688
|
-
}, closeButtonVisible && /*#__PURE__*/createElement(CloseButton, {
|
|
689
|
+
}, closeButtonVisible && /*#__PURE__*/React.createElement(CloseButton, {
|
|
689
690
|
"aria-label": closeButtonLabel,
|
|
690
691
|
light: closeButtonLight || color !== "white",
|
|
691
692
|
style: styles$1.closeButton,
|
|
@@ -744,7 +745,7 @@ const StyledImage = addStyle("img");
|
|
|
744
745
|
* main responsibility is populate the contents depending on the variation used.
|
|
745
746
|
*/
|
|
746
747
|
|
|
747
|
-
class PopoverContent extends Component {
|
|
748
|
+
class PopoverContent extends React.Component {
|
|
748
749
|
constructor(...args) {
|
|
749
750
|
super(...args);
|
|
750
751
|
|
|
@@ -759,8 +760,8 @@ class PopoverContent extends Component {
|
|
|
759
760
|
return null;
|
|
760
761
|
}
|
|
761
762
|
|
|
762
|
-
return /*#__PURE__*/createElement(View, {
|
|
763
|
-
style: [styles
|
|
763
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
764
|
+
style: [styles.image, placement === "bottom" && styles.imageToBottom]
|
|
764
765
|
}, image);
|
|
765
766
|
};
|
|
766
767
|
|
|
@@ -773,11 +774,11 @@ class PopoverContent extends Component {
|
|
|
773
774
|
return null;
|
|
774
775
|
}
|
|
775
776
|
|
|
776
|
-
return /*#__PURE__*/createElement(View, {
|
|
777
|
-
style: styles
|
|
778
|
-
}, typeof icon !== "string" ? icon : /*#__PURE__*/createElement(StyledImage, {
|
|
777
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
778
|
+
style: styles.iconContainer
|
|
779
|
+
}, typeof icon !== "string" ? icon : /*#__PURE__*/React.createElement(StyledImage, {
|
|
779
780
|
src: icon,
|
|
780
|
-
style: styles
|
|
781
|
+
style: styles.icon
|
|
781
782
|
}));
|
|
782
783
|
};
|
|
783
784
|
|
|
@@ -790,8 +791,8 @@ class PopoverContent extends Component {
|
|
|
790
791
|
return null;
|
|
791
792
|
}
|
|
792
793
|
|
|
793
|
-
return /*#__PURE__*/createElement(View, {
|
|
794
|
-
style: styles
|
|
794
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
795
|
+
style: styles.actions
|
|
795
796
|
}, typeof actions === "function" ? actions({
|
|
796
797
|
close: close
|
|
797
798
|
}) : actions);
|
|
@@ -835,7 +836,7 @@ class PopoverContent extends Component {
|
|
|
835
836
|
title,
|
|
836
837
|
testId
|
|
837
838
|
} = this.props;
|
|
838
|
-
return /*#__PURE__*/createElement(PopoverContext.Consumer, null, ({
|
|
839
|
+
return /*#__PURE__*/React.createElement(PopoverContext.Consumer, null, ({
|
|
839
840
|
close,
|
|
840
841
|
placement
|
|
841
842
|
}) => {
|
|
@@ -844,22 +845,22 @@ class PopoverContent extends Component {
|
|
|
844
845
|
close,
|
|
845
846
|
placement
|
|
846
847
|
});
|
|
847
|
-
return /*#__PURE__*/createElement(PopoverContentCore, {
|
|
848
|
+
return /*#__PURE__*/React.createElement(PopoverContentCore, {
|
|
848
849
|
color: emphasized ? "blue" : "white",
|
|
849
850
|
closeButtonLight: image && placement === "top",
|
|
850
851
|
closeButtonLabel: closeButtonLabel,
|
|
851
852
|
closeButtonVisible: closeButtonVisible,
|
|
852
853
|
style: style,
|
|
853
854
|
testId: testId
|
|
854
|
-
}, /*#__PURE__*/createElement(View, {
|
|
855
|
-
style: !!icon && styles
|
|
855
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
856
|
+
style: !!icon && styles.withIcon
|
|
856
857
|
}, this.maybeRenderImage({
|
|
857
858
|
placement
|
|
858
|
-
}), this.maybeRenderIcon(), /*#__PURE__*/createElement(View, {
|
|
859
|
-
style: styles
|
|
860
|
-
}, /*#__PURE__*/createElement(HeadingSmall, {
|
|
861
|
-
style: styles
|
|
862
|
-
}, title), /*#__PURE__*/createElement(Body, null, content))), this.maybeRenderActions(close));
|
|
859
|
+
}), this.maybeRenderIcon(), /*#__PURE__*/React.createElement(View, {
|
|
860
|
+
style: styles.text
|
|
861
|
+
}, /*#__PURE__*/React.createElement(HeadingSmall, {
|
|
862
|
+
style: styles.title
|
|
863
|
+
}, title), /*#__PURE__*/React.createElement(Body, null, content))), this.maybeRenderActions(close));
|
|
863
864
|
});
|
|
864
865
|
}
|
|
865
866
|
|
|
@@ -867,7 +868,7 @@ class PopoverContent extends Component {
|
|
|
867
868
|
PopoverContent.defaultProps = {
|
|
868
869
|
closeButtonVisible: false
|
|
869
870
|
};
|
|
870
|
-
const styles
|
|
871
|
+
const styles = StyleSheet.create({
|
|
871
872
|
/**
|
|
872
873
|
* Shared styles
|
|
873
874
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-popover",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -15,26 +15,25 @@
|
|
|
15
15
|
"author": "",
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@babel/runtime": "^7.
|
|
19
|
-
"@khanacademy/wonder-blocks-color": "^1.1.
|
|
20
|
-
"@khanacademy/wonder-blocks-core": "^
|
|
21
|
-
"@khanacademy/wonder-blocks-icon": "^1.2.
|
|
22
|
-
"@khanacademy/wonder-blocks-icon-button": "^3.
|
|
23
|
-
"@khanacademy/wonder-blocks-layout": "^1.4.
|
|
24
|
-
"@khanacademy/wonder-blocks-modal": "^2.
|
|
25
|
-
"@khanacademy/wonder-blocks-spacing": "^3.0.
|
|
26
|
-
"@khanacademy/wonder-blocks-tooltip": "^1.3.
|
|
27
|
-
"@khanacademy/wonder-blocks-typography": "^1.1.
|
|
18
|
+
"@babel/runtime": "^7.16.3",
|
|
19
|
+
"@khanacademy/wonder-blocks-color": "^1.1.20",
|
|
20
|
+
"@khanacademy/wonder-blocks-core": "^4.0.0",
|
|
21
|
+
"@khanacademy/wonder-blocks-icon": "^1.2.24",
|
|
22
|
+
"@khanacademy/wonder-blocks-icon-button": "^3.4.2",
|
|
23
|
+
"@khanacademy/wonder-blocks-layout": "^1.4.6",
|
|
24
|
+
"@khanacademy/wonder-blocks-modal": "^2.2.0",
|
|
25
|
+
"@khanacademy/wonder-blocks-spacing": "^3.0.5",
|
|
26
|
+
"@khanacademy/wonder-blocks-tooltip": "^1.3.6",
|
|
27
|
+
"@khanacademy/wonder-blocks-typography": "^1.1.28"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@popperjs/core": "^2.10.1",
|
|
31
31
|
"aphrodite": "^1.2.5",
|
|
32
|
-
"react": "
|
|
33
|
-
"react-dom": "
|
|
32
|
+
"react": "16.14.0",
|
|
33
|
+
"react-dom": "16.14.0",
|
|
34
34
|
"react-popper": "^2.0.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"wb-dev-build-settings": "^0.
|
|
38
|
-
}
|
|
39
|
-
"gitHead": "2a21f4ec19e5611fe716237c21f45c9164b65710"
|
|
37
|
+
"wb-dev-build-settings": "^0.2.0"
|
|
38
|
+
}
|
|
40
39
|
}
|
|
@@ -22,9 +22,9 @@ exports[`wonder-blocks-popover example 1 1`] = `
|
|
|
22
22
|
>
|
|
23
23
|
<button
|
|
24
24
|
aria-controls="uid-popover-0-wb-id"
|
|
25
|
+
aria-disabled={false}
|
|
25
26
|
aria-expanded="false"
|
|
26
27
|
className=""
|
|
27
|
-
disabled={false}
|
|
28
28
|
id="uid-popover-0-wb-id-anchor"
|
|
29
29
|
onBlur={[Function]}
|
|
30
30
|
onClick={[Function]}
|
|
@@ -142,9 +142,9 @@ exports[`wonder-blocks-popover example 2 1`] = `
|
|
|
142
142
|
>
|
|
143
143
|
<button
|
|
144
144
|
aria-controls="uid-popover-1-wb-id"
|
|
145
|
+
aria-disabled={false}
|
|
145
146
|
aria-expanded="true"
|
|
146
147
|
className=""
|
|
147
|
-
disabled={false}
|
|
148
148
|
id="uid-popover-1-wb-id-anchor"
|
|
149
149
|
onBlur={[Function]}
|
|
150
150
|
onClick={[Function]}
|
|
@@ -242,8 +242,8 @@ exports[`wonder-blocks-popover example 2 1`] = `
|
|
|
242
242
|
}
|
|
243
243
|
/>
|
|
244
244
|
<button
|
|
245
|
+
aria-disabled={false}
|
|
245
246
|
className=""
|
|
246
|
-
disabled={false}
|
|
247
247
|
onBlur={[Function]}
|
|
248
248
|
onClick={[Function]}
|
|
249
249
|
onDragStart={[Function]}
|
|
@@ -339,9 +339,9 @@ exports[`wonder-blocks-popover example 3 1`] = `
|
|
|
339
339
|
>
|
|
340
340
|
<button
|
|
341
341
|
aria-controls="uid-popover-2-wb-id"
|
|
342
|
+
aria-disabled={false}
|
|
342
343
|
aria-expanded="false"
|
|
343
344
|
className=""
|
|
344
|
-
disabled={false}
|
|
345
345
|
id="uid-popover-2-wb-id-anchor"
|
|
346
346
|
onBlur={[Function]}
|
|
347
347
|
onClick={[Function]}
|
|
@@ -437,9 +437,9 @@ exports[`wonder-blocks-popover example 4 1`] = `
|
|
|
437
437
|
>
|
|
438
438
|
<button
|
|
439
439
|
aria-controls="uid-popover-3-wb-id"
|
|
440
|
+
aria-disabled={false}
|
|
440
441
|
aria-expanded="false"
|
|
441
442
|
className=""
|
|
442
|
-
disabled={false}
|
|
443
443
|
id="uid-popover-3-wb-id-anchor"
|
|
444
444
|
onBlur={[Function]}
|
|
445
445
|
onClick={[Function]}
|
|
@@ -535,9 +535,9 @@ exports[`wonder-blocks-popover example 5 1`] = `
|
|
|
535
535
|
>
|
|
536
536
|
<button
|
|
537
537
|
aria-controls="uid-popover-4-wb-id"
|
|
538
|
+
aria-disabled={false}
|
|
538
539
|
aria-expanded="false"
|
|
539
540
|
className=""
|
|
540
|
-
disabled={false}
|
|
541
541
|
id="uid-popover-4-wb-id-anchor"
|
|
542
542
|
onBlur={[Function]}
|
|
543
543
|
onClick={[Function]}
|
|
@@ -969,8 +969,8 @@ exports[`wonder-blocks-popover example 7 1`] = `
|
|
|
969
969
|
}
|
|
970
970
|
>
|
|
971
971
|
<button
|
|
972
|
+
aria-disabled={false}
|
|
972
973
|
className=""
|
|
973
|
-
disabled={false}
|
|
974
974
|
onBlur={[Function]}
|
|
975
975
|
onClick={[Function]}
|
|
976
976
|
onDragStart={[Function]}
|
|
@@ -1070,8 +1070,8 @@ exports[`wonder-blocks-popover example 7 1`] = `
|
|
|
1070
1070
|
}
|
|
1071
1071
|
/>
|
|
1072
1072
|
<button
|
|
1073
|
+
aria-disabled={false}
|
|
1073
1074
|
className=""
|
|
1074
|
-
disabled={false}
|
|
1075
1075
|
onBlur={[Function]}
|
|
1076
1076
|
onClick={[Function]}
|
|
1077
1077
|
onDragStart={[Function]}
|
|
@@ -2,13 +2,33 @@
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import * as ReactDOM from "react-dom";
|
|
4
4
|
import {mount} from "enzyme";
|
|
5
|
+
import "jest-enzyme";
|
|
5
6
|
|
|
6
7
|
import FocusManager from "../focus-manager.js";
|
|
7
8
|
import {findFocusableNodes} from "../../util/util.js";
|
|
8
9
|
|
|
10
|
+
import {unmountAll} from "../../../../../utils/testing/enzyme-shim.js";
|
|
11
|
+
import {getElementAttachedToDocument} from "../../../../../utils/testing/get-element-attached-to-document.js";
|
|
12
|
+
|
|
9
13
|
describe("FocusManager", () => {
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
jest.useRealTimers();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
unmountAll();
|
|
20
|
+
if (document.body) {
|
|
21
|
+
document.body.innerHTML = "";
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
10
25
|
it("should focus on the first focusable element inside the popover", async () => {
|
|
11
26
|
// Arrange
|
|
27
|
+
// We need the elements in the DOM document for the focus() calls to
|
|
28
|
+
// work.
|
|
29
|
+
const containerDiv = getElementAttachedToDocument("container");
|
|
30
|
+
const focusManagerDiv = getElementAttachedToDocument("focusManagerDiv");
|
|
31
|
+
|
|
12
32
|
const ref = await new Promise((resolve) => {
|
|
13
33
|
const nodes = (
|
|
14
34
|
<div ref={resolve}>
|
|
@@ -16,7 +36,7 @@ describe("FocusManager", () => {
|
|
|
16
36
|
<button data-next />
|
|
17
37
|
</div>
|
|
18
38
|
);
|
|
19
|
-
mount(nodes);
|
|
39
|
+
mount(nodes, {attachTo: containerDiv});
|
|
20
40
|
});
|
|
21
41
|
const domNode = ((ReactDOM.findDOMNode(ref): any): HTMLElement);
|
|
22
42
|
|
|
@@ -38,10 +58,10 @@ describe("FocusManager", () => {
|
|
|
38
58
|
<button data-tab-index="2" />
|
|
39
59
|
</div>
|
|
40
60
|
</FocusManager>,
|
|
61
|
+
{attachTo: focusManagerDiv},
|
|
41
62
|
);
|
|
42
63
|
|
|
43
64
|
// Act
|
|
44
|
-
|
|
45
65
|
// focus on the previous element before the popover (anchor element)
|
|
46
66
|
anchorElementNode.focus();
|
|
47
67
|
// press `tab` to focus on the next element
|
|
@@ -61,6 +81,11 @@ describe("FocusManager", () => {
|
|
|
61
81
|
|
|
62
82
|
it("should focus on the last focusable element inside the popover", async () => {
|
|
63
83
|
// Arrange
|
|
84
|
+
// We need the elements in the DOM document for the focus() calls to
|
|
85
|
+
// work.
|
|
86
|
+
const containerDiv = getElementAttachedToDocument("container");
|
|
87
|
+
const focusManagerDiv = getElementAttachedToDocument("focusManagerDiv");
|
|
88
|
+
|
|
64
89
|
const ref = await new Promise((resolve) => {
|
|
65
90
|
const nodes = (
|
|
66
91
|
<div ref={resolve}>
|
|
@@ -68,7 +93,7 @@ describe("FocusManager", () => {
|
|
|
68
93
|
<button data-next />
|
|
69
94
|
</div>
|
|
70
95
|
);
|
|
71
|
-
mount(nodes);
|
|
96
|
+
mount(nodes, {attachTo: containerDiv});
|
|
72
97
|
});
|
|
73
98
|
const domNode = ((ReactDOM.findDOMNode(ref): any): HTMLElement);
|
|
74
99
|
|
|
@@ -90,6 +115,7 @@ describe("FocusManager", () => {
|
|
|
90
115
|
<button data-tab-index="2" />
|
|
91
116
|
</div>
|
|
92
117
|
</FocusManager>,
|
|
118
|
+
{attachTo: focusManagerDiv},
|
|
93
119
|
);
|
|
94
120
|
|
|
95
121
|
// Act
|
|
@@ -161,9 +161,8 @@ export default class Popover extends React.Component<Props, State> {
|
|
|
161
161
|
/**
|
|
162
162
|
* Popover content ref
|
|
163
163
|
*/
|
|
164
|
-
contentRef: RefObject<
|
|
165
|
-
|
|
166
|
-
> = React.createRef();
|
|
164
|
+
contentRef: RefObject<PopoverContent | PopoverContentCore> =
|
|
165
|
+
React.createRef();
|
|
167
166
|
|
|
168
167
|
/**
|
|
169
168
|
* Popover dialog closed
|
|
@@ -11,7 +11,14 @@ import Popover from "./popover.js";
|
|
|
11
11
|
import PopoverContent from "./popover-content.js";
|
|
12
12
|
|
|
13
13
|
export default {
|
|
14
|
-
title: "Popover",
|
|
14
|
+
title: "Floating/Popover",
|
|
15
|
+
parameters: {
|
|
16
|
+
// TODO(WB-1170): Reassess this after investigating more about Chromatic
|
|
17
|
+
// flakyness.
|
|
18
|
+
chromatic: {
|
|
19
|
+
delay: 400,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
15
22
|
};
|
|
16
23
|
|
|
17
24
|
const styles = StyleSheet.create({
|
|
@@ -57,7 +64,7 @@ const BasePopoverExample = ({placement}: {|placement: Placement|}) => {
|
|
|
57
64
|
);
|
|
58
65
|
};
|
|
59
66
|
|
|
60
|
-
export const
|
|
67
|
+
export const PopoverAlignment: StoryComponentType = () => (
|
|
61
68
|
<View style={styles.container}>
|
|
62
69
|
<BasePopoverExample placement="left" />
|
|
63
70
|
<BasePopoverExample placement="bottom" />
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2018 Khan Academy
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|