@khanacademy/wonder-blocks-popover 6.1.57 → 6.2.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 +21 -0
- package/dist/components/popover.d.ts +5 -0
- package/dist/es/index.js +3 -3
- package/dist/index.js +2 -2
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-popover
|
|
2
2
|
|
|
3
|
+
## 6.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 00e6dda: Updates internal WB typography references to use the new system (Heading and BodyText)
|
|
8
|
+
- Updated dependencies [488728a]
|
|
9
|
+
- Updated dependencies [00e6dda]
|
|
10
|
+
- Updated dependencies [00e6dda]
|
|
11
|
+
- @khanacademy/wonder-blocks-tokens@16.2.0
|
|
12
|
+
- @khanacademy/wonder-blocks-tooltip@4.1.71
|
|
13
|
+
- @khanacademy/wonder-blocks-typography@4.3.0
|
|
14
|
+
- @khanacademy/wonder-blocks-icon-button@11.2.1
|
|
15
|
+
- @khanacademy/wonder-blocks-modal@8.6.2
|
|
16
|
+
- @khanacademy/wonder-blocks-styles@0.2.41
|
|
17
|
+
|
|
18
|
+
## 6.2.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- 6ecb7cc: Add autoUpdate prop to Popover component
|
|
23
|
+
|
|
3
24
|
## 6.1.57
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -6,6 +6,11 @@ import PopoverContent from "./popover-content";
|
|
|
6
6
|
import PopoverContentCore from "./popover-content-core";
|
|
7
7
|
type PopoverContents = React.ReactElement<React.ComponentProps<typeof PopoverContent>> | React.ReactElement<React.ComponentProps<typeof PopoverContentCore>>;
|
|
8
8
|
type Props = AriaProps & Readonly<{
|
|
9
|
+
/**
|
|
10
|
+
* Whether the popover should update its position when the anchor
|
|
11
|
+
* element changes size or position. Defaults to false.
|
|
12
|
+
*/
|
|
13
|
+
autoUpdate?: boolean;
|
|
9
14
|
/**
|
|
10
15
|
* The element that triggers the popover. This element will be used to
|
|
11
16
|
* position the popover. It can be either a Node or a function using the
|
package/dist/es/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { TooltipTail, TooltipPopper } from '@khanacademy/wonder-blocks-tooltip';
|
|
|
6
6
|
import { maybeGetPortalMountedModalHostElement } from '@khanacademy/wonder-blocks-modal';
|
|
7
7
|
import { StyleSheet } from 'aphrodite';
|
|
8
8
|
import { border, semanticColor, boxShadow, spacing } from '@khanacademy/wonder-blocks-tokens';
|
|
9
|
-
import {
|
|
9
|
+
import { Heading, BodyText } from '@khanacademy/wonder-blocks-typography';
|
|
10
10
|
import { actionStyles } from '@khanacademy/wonder-blocks-styles';
|
|
11
11
|
import xIcon from '@phosphor-icons/core/regular/x.svg';
|
|
12
12
|
import IconButton from '@khanacademy/wonder-blocks-icon-button';
|
|
@@ -25,12 +25,12 @@ class InitialFocus extends React.Component{componentDidMount(){const node=ReactD
|
|
|
25
25
|
|
|
26
26
|
class FocusManager extends React.Component{componentDidMount(){this.addEventListeners();}componentDidUpdate(){this.removeEventListeners();this.addEventListeners();}componentWillUnmount(){this.changeFocusabilityInsidePopover(true);this.removeEventListeners();}removeEventListeners(){const{anchorElement}=this.props;if(anchorElement){anchorElement.removeEventListener("keydown",this.handleKeydownPreviousFocusableElement);}if(!this.nextElementAfterPopover){window.removeEventListener("blur",()=>{this.changeFocusabilityInsidePopover(true);});}if(this.firstFocusableElementInPopover){this.firstFocusableElementInPopover.removeEventListener("keydown",this.handleKeydownFirstFocusableElement);}if(this.lastFocusableElementInPopover){this.lastFocusableElementInPopover.removeEventListener("keydown",this.handleKeydownLastFocusableElement);}if(this.nextElementAfterPopover){this.nextElementAfterPopover.removeEventListener("keydown",this.handleKeydownNextFocusableElement);}}render(){const{children}=this.props;return jsx("div",{ref:this.getComponentRootNode,onClick:()=>{this.changeFocusabilityInsidePopover(true);},onFocus:()=>{this.changeFocusabilityInsidePopover(true);},onBlur:()=>{this.changeFocusabilityInsidePopover(false);},children:jsx(InitialFocus,{initialFocusId:this.props.initialFocusId,delay:this.props.initialFocusDelay,children:children})})}constructor(...args){super(...args),this.elementsThatCanBeFocusableInsidePopover=[],this.firstFocusableElementInPopover=null,this.lastFocusableElementInPopover=null,this.addEventListeners=()=>{const{anchorElement}=this.props;if(anchorElement){anchorElement.addEventListener("keydown",this.handleKeydownPreviousFocusableElement);}if(this.rootNode){this.elementsThatCanBeFocusableInsidePopover=findFocusableNodes(this.rootNode);this.firstFocusableElementInPopover=this.elementsThatCanBeFocusableInsidePopover[0];this.lastFocusableElementInPopover=this.elementsThatCanBeFocusableInsidePopover[this.elementsThatCanBeFocusableInsidePopover.length-1];}this.nextElementAfterPopover=this.getNextFocusableElement();if(!this.nextElementAfterPopover){window.addEventListener("blur",()=>{this.changeFocusabilityInsidePopover(true);});}if(this.firstFocusableElementInPopover){this.firstFocusableElementInPopover.addEventListener("keydown",this.handleKeydownFirstFocusableElement);}if(this.lastFocusableElementInPopover){this.lastFocusableElementInPopover.addEventListener("keydown",this.handleKeydownLastFocusableElement);}if(this.nextElementAfterPopover){this.nextElementAfterPopover.addEventListener("keydown",this.handleKeydownNextFocusableElement);}},this.handleKeydownFirstFocusableElement=e=>{if(e.key===keys.tab&&e.shiftKey){e.preventDefault();this.props.anchorElement?.focus();}},this.handleKeydownLastFocusableElement=e=>{if(this.nextElementAfterPopover&&e.key===keys.tab&&!e.shiftKey){e.preventDefault();this.nextElementAfterPopover?.focus();}if(e.key===keys.tab&&!e.shiftKey){this.props.onFocusOut?.();}},this.getNextFocusableElement=()=>{const{anchorElement}=this.props;if(!anchorElement){return}const focusableElements=findFocusableNodes(document);const focusableElementsOutside=focusableElements.filter(element=>{const index=this.elementsThatCanBeFocusableInsidePopover.indexOf(element);return index<0});const anchorIndex=focusableElementsOutside.indexOf(anchorElement);if(anchorIndex>=0&&anchorIndex!==focusableElementsOutside.length-1){const nextElementIndex=anchorIndex<focusableElementsOutside.length-1?anchorIndex+1:0;return focusableElementsOutside[nextElementIndex]}return},this.getComponentRootNode=node=>{if(!node){return}const rootNode=ReactDOM.findDOMNode(node);if(!rootNode){throw new Error("Assertion error: root node should exist after mount")}this.rootNode=rootNode;},this.changeFocusabilityInsidePopover=(enabled=true)=>{const tabIndex=enabled?"0":"-1";this.elementsThatCanBeFocusableInsidePopover.forEach(element=>{element.setAttribute("tabIndex",tabIndex);});},this.handleKeydownPreviousFocusableElement=e=>{if(e.key===keys.tab&&!e.shiftKey){e.preventDefault();this.firstFocusableElementInPopover?.focus();}if(e.key===keys.tab&&e.shiftKey){this.props.onFocusOut?.();}},this.handleKeydownNextFocusableElement=e=>{if(e.key===keys.tab&&e.shiftKey){e.preventDefault();this.lastFocusableElementInPopover?.focus();}};}}
|
|
27
27
|
|
|
28
|
-
class Popover extends React.Component{static getDerivedStateFromProps(props,state){return {opened:typeof props.opened==="boolean"?props.opened:state.opened}}renderContent(uniqueId){const{content}=this.props;const popoverContents=typeof content==="function"?content({close:this.handleClose}):content;return React.cloneElement(popoverContents,{ref:this.contentRef,uniqueId})}renderPopper(uniqueId){const{dismissEnabled,initialFocusId,placement,showTail,portal,"aria-label":ariaLabel,"aria-describedby":ariaDescribedBy,rootBoundary,viewportPadding,initialFocusDelay}=this.props;const{anchorElement}=this.state;const describedBy=ariaDescribedBy||`${uniqueId}-content`;const ariaLabelledBy=ariaLabel?undefined:`${uniqueId}-title`;const popperContent=jsx(TooltipPopper,{anchorElement:anchorElement,placement:placement,rootBoundary:rootBoundary,viewportPadding:viewportPadding,children:props=>jsx(PopoverDialog,{...props,"aria-label":ariaLabel,"aria-describedby":describedBy,"aria-labelledby":ariaLabelledBy,id:uniqueId,onUpdate:placement=>this.setState({placement}),showTail:showTail,children:this.renderContent(uniqueId)})});if(portal){return jsx(FocusManager,{anchorElement:anchorElement,initialFocusId:initialFocusId,initialFocusDelay:initialFocusDelay,onFocusOut:dismissEnabled?this.handleClose:undefined,children:popperContent})}else {return jsx(InitialFocus,{initialFocusId:initialFocusId,delay:initialFocusDelay,children:popperContent})}}getHost(){return maybeGetPortalMountedModalHostElement(this.state.anchorElement)||document.body}renderPortal(uniqueId,opened){if(!opened){return null}const{portal}=this.props;const popperHost=this.getHost();if(portal&&popperHost){return ReactDOM.createPortal(this.renderPopper(uniqueId),popperHost)}return this.renderPopper(uniqueId)}render(){const{children,dismissEnabled,id}=this.props;const{opened,placement}=this.state;return jsxs(PopoverContext.Provider,{value:{close:this.handleClose,placement:placement},children:[jsx(Id,{id:id,children:uniqueId=>jsxs(React.Fragment,{children:[jsx(PopoverAnchor,{anchorRef:this.updateRef,id:`${uniqueId}-anchor`,"aria-controls":uniqueId,"aria-expanded":opened?"true":"false",onClick:this.handleOpen,children:children}),this.renderPortal(uniqueId,opened)]})}),dismissEnabled&&opened&&jsx(PopoverEventListener,{onClose:this.handleClose,contentRef:this.contentRef})]})}constructor(...args){super(...args),this.state={opened:!!this.props.opened,placement:this.props.placement},this.contentRef=React.createRef(),this.maybeReturnFocus=()=>{const{anchorElement}=this.state;const{closedFocusId}=this.props;if(closedFocusId){const focusElement=ReactDOM.findDOMNode(document.getElementById(closedFocusId));focusElement?.focus();return}if(anchorElement){anchorElement.focus();}},this.handleClose=(shouldReturnFocus=true)=>{this.setState({opened:false},()=>{this.props.onClose?.();if(shouldReturnFocus){this.maybeReturnFocus();}});},this.handleOpen=()=>{if(this.props.dismissEnabled&&this.state.opened){this.handleClose(true);}else {this.setState({opened:true});}},this.updateRef=actualRef=>{if(actualRef&&this.state.anchorElement!==actualRef){this.setState({anchorElement:actualRef});}};}}Popover.defaultProps={placement:"top",showTail:true,portal:true,rootBoundary:"viewport"};
|
|
28
|
+
class Popover extends React.Component{static getDerivedStateFromProps(props,state){return {opened:typeof props.opened==="boolean"?props.opened:state.opened}}renderContent(uniqueId){const{content}=this.props;const popoverContents=typeof content==="function"?content({close:this.handleClose}):content;return React.cloneElement(popoverContents,{ref:this.contentRef,uniqueId})}renderPopper(uniqueId){const{autoUpdate,dismissEnabled,initialFocusId,placement,showTail,portal,"aria-label":ariaLabel,"aria-describedby":ariaDescribedBy,rootBoundary,viewportPadding,initialFocusDelay}=this.props;const{anchorElement}=this.state;const describedBy=ariaDescribedBy||`${uniqueId}-content`;const ariaLabelledBy=ariaLabel?undefined:`${uniqueId}-title`;const shouldAnchorExist=autoUpdate?anchorElement:true;if(!shouldAnchorExist){return null}const popperContent=jsx(TooltipPopper,{anchorElement:anchorElement,autoUpdate:autoUpdate,placement:placement,rootBoundary:rootBoundary,viewportPadding:viewportPadding,children:props=>jsx(PopoverDialog,{...props,"aria-label":ariaLabel,"aria-describedby":describedBy,"aria-labelledby":ariaLabelledBy,id:uniqueId,onUpdate:placement=>this.setState({placement}),showTail:showTail,children:this.renderContent(uniqueId)})});if(portal){return jsx(FocusManager,{anchorElement:anchorElement,initialFocusId:initialFocusId,initialFocusDelay:initialFocusDelay,onFocusOut:dismissEnabled?this.handleClose:undefined,children:popperContent})}else {return jsx(InitialFocus,{initialFocusId:initialFocusId,delay:initialFocusDelay,children:popperContent})}}getHost(){return maybeGetPortalMountedModalHostElement(this.state.anchorElement)||document.body}renderPortal(uniqueId,opened){if(!opened){return null}const{portal}=this.props;const popperHost=this.getHost();if(portal&&popperHost){return ReactDOM.createPortal(this.renderPopper(uniqueId),popperHost)}return this.renderPopper(uniqueId)}render(){const{children,dismissEnabled,id}=this.props;const{opened,placement}=this.state;return jsxs(PopoverContext.Provider,{value:{close:this.handleClose,placement:placement},children:[jsx(Id,{id:id,children:uniqueId=>jsxs(React.Fragment,{children:[jsx(PopoverAnchor,{anchorRef:this.updateRef,id:`${uniqueId}-anchor`,"aria-controls":uniqueId,"aria-expanded":opened?"true":"false",onClick:this.handleOpen,children:children}),this.renderPortal(uniqueId,opened)]})}),dismissEnabled&&opened&&jsx(PopoverEventListener,{onClose:this.handleClose,contentRef:this.contentRef})]})}constructor(...args){super(...args),this.state={opened:!!this.props.opened,placement:this.props.placement},this.contentRef=React.createRef(),this.maybeReturnFocus=()=>{const{anchorElement}=this.state;const{closedFocusId}=this.props;if(closedFocusId){const focusElement=ReactDOM.findDOMNode(document.getElementById(closedFocusId));focusElement?.focus();return}if(anchorElement){anchorElement.focus();}},this.handleClose=(shouldReturnFocus=true)=>{this.setState({opened:false},()=>{this.props.onClose?.();if(shouldReturnFocus){this.maybeReturnFocus();}});},this.handleOpen=()=>{if(this.props.dismissEnabled&&this.state.opened){this.handleClose(true);}else {this.setState({opened:true});}},this.updateRef=actualRef=>{if(actualRef&&this.state.anchorElement!==actualRef){this.setState({anchorElement:actualRef});}};}}Popover.defaultProps={placement:"top",showTail:true,portal:true,rootBoundary:"viewport"};
|
|
29
29
|
|
|
30
30
|
class CloseButton extends React.Component{render(){const{"aria-label":ariaLabel,style,testId}=this.props;return jsx(PopoverContext.Consumer,{children:({close})=>{return jsx(IconButton,{icon:xIcon,"aria-label":ariaLabel,onClick:close,kind:"tertiary",actionType:"neutral",style:style,testId:testId})}})}}CloseButton.defaultProps={"aria-label":"Close Popover"};
|
|
31
31
|
|
|
32
32
|
class PopoverContentCore extends React.Component{render(){const{"aria-label":ariaLabel,children,closeButtonLight,closeButtonLabel,closeButtonVisible,style,testId}=this.props;return jsxs(View,{testId:testId,style:[styles$1.content,style],"aria-label":ariaLabel,children:[closeButtonVisible&&jsx(CloseButton,{"aria-label":closeButtonLabel,style:[styles$1.closeButton,closeButtonLight&&actionStyles.inverse],testId:`${testId||"popover"}-close-btn`}),children]})}}PopoverContentCore.defaultProps={closeButtonLight:false,closeButtonVisible:false};const styles$1=StyleSheet.create({content:{borderRadius:border.radius.radius_040,border:`solid 1px ${semanticColor.core.border.neutral.subtle}`,backgroundColor:semanticColor.core.background.base.default,boxShadow:boxShadow.mid,margin:0,maxWidth:spacing.medium_16*18,padding:spacing.large_24,overflow:"hidden",justifyContent:"center"},closeButton:{margin:0,position:"absolute",right:spacing.xxxSmall_4,top:spacing.xxxSmall_4,zIndex:1}});
|
|
33
33
|
|
|
34
|
-
const StyledImg=addStyle("img");class PopoverContent extends React.Component{componentDidMount(){const{icon,image}=this.props;if(image&&icon){throw new Error("'image' and 'icon' cannot be used at the same time. You can fix this by either removing 'image' or 'icon' from your instance.")}}validateProps({placement}){if(this.props.image&&(placement==="left"||placement==="right")){throw new Error("'image' can only be vertically placed. You can fix this by either changing `placement` to `top` or `bottom` or removing the `image` prop inside `content`.")}}render(){const{closeButtonLabel,closeButtonVisible,content,icon,image,style,title,testId,uniqueId}=this.props;return jsx(PopoverContext.Consumer,{children:({close,placement})=>{this.validateProps({close,placement});return jsxs(PopoverContentCore,{closeButtonLight:image&&placement==="top",closeButtonLabel:closeButtonLabel,closeButtonVisible:closeButtonVisible,style:style,testId:testId,children:[jsxs(View,{style:!!icon&&styles.withIcon,children:[this.maybeRenderImage({placement}),this.maybeRenderIcon(),jsxs(View,{style:styles.text,children:[jsx(
|
|
34
|
+
const StyledImg=addStyle("img");class PopoverContent extends React.Component{componentDidMount(){const{icon,image}=this.props;if(image&&icon){throw new Error("'image' and 'icon' cannot be used at the same time. You can fix this by either removing 'image' or 'icon' from your instance.")}}validateProps({placement}){if(this.props.image&&(placement==="left"||placement==="right")){throw new Error("'image' can only be vertically placed. You can fix this by either changing `placement` to `top` or `bottom` or removing the `image` prop inside `content`.")}}render(){const{closeButtonLabel,closeButtonVisible,content,icon,image,style,title,testId,uniqueId}=this.props;return jsx(PopoverContext.Consumer,{children:({close,placement})=>{this.validateProps({close,placement});return jsxs(PopoverContentCore,{closeButtonLight:image&&placement==="top",closeButtonLabel:closeButtonLabel,closeButtonVisible:closeButtonVisible,style:style,testId:testId,children:[jsxs(View,{style:!!icon&&styles.withIcon,children:[this.maybeRenderImage({placement}),this.maybeRenderIcon(),jsxs(View,{style:styles.text,children:[jsx(Heading,{size:"medium",id:`${uniqueId}-title`,style:styles.title,children:title}),jsx(BodyText,{tag:"span",id:`${uniqueId}-content`,children:content})]})]}),this.maybeRenderActions(close)]})}})}constructor(...args){super(...args),this.maybeRenderImage=({placement})=>{const{image}=this.props;if(!image){return null}return jsx(View,{style:[styles.image,placement==="bottom"&&styles.imageToBottom],children:image})},this.maybeRenderIcon=()=>{const{icon,iconAlt}=this.props;if(!icon){return null}return jsx(View,{style:styles.iconContainer,children:typeof icon!=="string"?icon:jsx(StyledImg,{src:icon,style:styles.icon,alt:iconAlt||""})})},this.maybeRenderActions=close=>{const{actions}=this.props;if(!actions){return null}return jsx(View,{style:styles.actions,children:typeof actions==="function"?actions({close:close}):actions})};}}PopoverContent.defaultProps={closeButtonVisible:false};const styles=StyleSheet.create({actions:{marginTop:spacing.large_24,flexDirection:"row",alignItems:"center",justifyContent:"flex-end"},text:{justifyContent:"center"},title:{marginBottom:spacing.xSmall_8},iconContainer:{alignItems:"center",justifyContent:"center",height:spacing.xxxLarge_64,width:spacing.xxxLarge_64,minWidth:spacing.xxxLarge_64,marginRight:spacing.medium_16,overflow:"hidden"},icon:{width:"100%"},withIcon:{flexDirection:"row"},image:{marginBottom:spacing.large_24,marginLeft:-spacing.large_24,marginRight:-spacing.large_24,marginTop:-spacing.large_24,width:`calc(100% + ${spacing.large_24*2}px)`},imageToBottom:{marginBottom:-spacing.large_24,marginTop:spacing.large_24,order:1}});
|
|
35
35
|
|
|
36
36
|
export { Popover, PopoverContent, PopoverContentCore };
|
package/dist/index.js
CHANGED
|
@@ -54,13 +54,13 @@ class InitialFocus extends React__namespace.Component{componentDidMount(){const
|
|
|
54
54
|
|
|
55
55
|
class FocusManager extends React__namespace.Component{componentDidMount(){this.addEventListeners();}componentDidUpdate(){this.removeEventListeners();this.addEventListeners();}componentWillUnmount(){this.changeFocusabilityInsidePopover(true);this.removeEventListeners();}removeEventListeners(){const{anchorElement}=this.props;if(anchorElement){anchorElement.removeEventListener("keydown",this.handleKeydownPreviousFocusableElement);}if(!this.nextElementAfterPopover){window.removeEventListener("blur",()=>{this.changeFocusabilityInsidePopover(true);});}if(this.firstFocusableElementInPopover){this.firstFocusableElementInPopover.removeEventListener("keydown",this.handleKeydownFirstFocusableElement);}if(this.lastFocusableElementInPopover){this.lastFocusableElementInPopover.removeEventListener("keydown",this.handleKeydownLastFocusableElement);}if(this.nextElementAfterPopover){this.nextElementAfterPopover.removeEventListener("keydown",this.handleKeydownNextFocusableElement);}}render(){const{children}=this.props;return jsxRuntime.jsx("div",{ref:this.getComponentRootNode,onClick:()=>{this.changeFocusabilityInsidePopover(true);},onFocus:()=>{this.changeFocusabilityInsidePopover(true);},onBlur:()=>{this.changeFocusabilityInsidePopover(false);},children:jsxRuntime.jsx(InitialFocus,{initialFocusId:this.props.initialFocusId,delay:this.props.initialFocusDelay,children:children})})}constructor(...args){super(...args),this.elementsThatCanBeFocusableInsidePopover=[],this.firstFocusableElementInPopover=null,this.lastFocusableElementInPopover=null,this.addEventListeners=()=>{const{anchorElement}=this.props;if(anchorElement){anchorElement.addEventListener("keydown",this.handleKeydownPreviousFocusableElement);}if(this.rootNode){this.elementsThatCanBeFocusableInsidePopover=findFocusableNodes(this.rootNode);this.firstFocusableElementInPopover=this.elementsThatCanBeFocusableInsidePopover[0];this.lastFocusableElementInPopover=this.elementsThatCanBeFocusableInsidePopover[this.elementsThatCanBeFocusableInsidePopover.length-1];}this.nextElementAfterPopover=this.getNextFocusableElement();if(!this.nextElementAfterPopover){window.addEventListener("blur",()=>{this.changeFocusabilityInsidePopover(true);});}if(this.firstFocusableElementInPopover){this.firstFocusableElementInPopover.addEventListener("keydown",this.handleKeydownFirstFocusableElement);}if(this.lastFocusableElementInPopover){this.lastFocusableElementInPopover.addEventListener("keydown",this.handleKeydownLastFocusableElement);}if(this.nextElementAfterPopover){this.nextElementAfterPopover.addEventListener("keydown",this.handleKeydownNextFocusableElement);}},this.handleKeydownFirstFocusableElement=e=>{if(e.key===wonderBlocksCore.keys.tab&&e.shiftKey){e.preventDefault();this.props.anchorElement?.focus();}},this.handleKeydownLastFocusableElement=e=>{if(this.nextElementAfterPopover&&e.key===wonderBlocksCore.keys.tab&&!e.shiftKey){e.preventDefault();this.nextElementAfterPopover?.focus();}if(e.key===wonderBlocksCore.keys.tab&&!e.shiftKey){this.props.onFocusOut?.();}},this.getNextFocusableElement=()=>{const{anchorElement}=this.props;if(!anchorElement){return}const focusableElements=findFocusableNodes(document);const focusableElementsOutside=focusableElements.filter(element=>{const index=this.elementsThatCanBeFocusableInsidePopover.indexOf(element);return index<0});const anchorIndex=focusableElementsOutside.indexOf(anchorElement);if(anchorIndex>=0&&anchorIndex!==focusableElementsOutside.length-1){const nextElementIndex=anchorIndex<focusableElementsOutside.length-1?anchorIndex+1:0;return focusableElementsOutside[nextElementIndex]}return},this.getComponentRootNode=node=>{if(!node){return}const rootNode=ReactDOM__namespace.findDOMNode(node);if(!rootNode){throw new Error("Assertion error: root node should exist after mount")}this.rootNode=rootNode;},this.changeFocusabilityInsidePopover=(enabled=true)=>{const tabIndex=enabled?"0":"-1";this.elementsThatCanBeFocusableInsidePopover.forEach(element=>{element.setAttribute("tabIndex",tabIndex);});},this.handleKeydownPreviousFocusableElement=e=>{if(e.key===wonderBlocksCore.keys.tab&&!e.shiftKey){e.preventDefault();this.firstFocusableElementInPopover?.focus();}if(e.key===wonderBlocksCore.keys.tab&&e.shiftKey){this.props.onFocusOut?.();}},this.handleKeydownNextFocusableElement=e=>{if(e.key===wonderBlocksCore.keys.tab&&e.shiftKey){e.preventDefault();this.lastFocusableElementInPopover?.focus();}};}}
|
|
56
56
|
|
|
57
|
-
class Popover extends React__namespace.Component{static getDerivedStateFromProps(props,state){return {opened:typeof props.opened==="boolean"?props.opened:state.opened}}renderContent(uniqueId){const{content}=this.props;const popoverContents=typeof content==="function"?content({close:this.handleClose}):content;return React__namespace.cloneElement(popoverContents,{ref:this.contentRef,uniqueId})}renderPopper(uniqueId){const{dismissEnabled,initialFocusId,placement,showTail,portal,"aria-label":ariaLabel,"aria-describedby":ariaDescribedBy,rootBoundary,viewportPadding,initialFocusDelay}=this.props;const{anchorElement}=this.state;const describedBy=ariaDescribedBy||`${uniqueId}-content`;const ariaLabelledBy=ariaLabel?undefined:`${uniqueId}-title`;const popperContent=jsxRuntime.jsx(wonderBlocksTooltip.TooltipPopper,{anchorElement:anchorElement,placement:placement,rootBoundary:rootBoundary,viewportPadding:viewportPadding,children:props=>jsxRuntime.jsx(PopoverDialog,{...props,"aria-label":ariaLabel,"aria-describedby":describedBy,"aria-labelledby":ariaLabelledBy,id:uniqueId,onUpdate:placement=>this.setState({placement}),showTail:showTail,children:this.renderContent(uniqueId)})});if(portal){return jsxRuntime.jsx(FocusManager,{anchorElement:anchorElement,initialFocusId:initialFocusId,initialFocusDelay:initialFocusDelay,onFocusOut:dismissEnabled?this.handleClose:undefined,children:popperContent})}else {return jsxRuntime.jsx(InitialFocus,{initialFocusId:initialFocusId,delay:initialFocusDelay,children:popperContent})}}getHost(){return wonderBlocksModal.maybeGetPortalMountedModalHostElement(this.state.anchorElement)||document.body}renderPortal(uniqueId,opened){if(!opened){return null}const{portal}=this.props;const popperHost=this.getHost();if(portal&&popperHost){return ReactDOM__namespace.createPortal(this.renderPopper(uniqueId),popperHost)}return this.renderPopper(uniqueId)}render(){const{children,dismissEnabled,id}=this.props;const{opened,placement}=this.state;return jsxRuntime.jsxs(PopoverContext.Provider,{value:{close:this.handleClose,placement:placement},children:[jsxRuntime.jsx(wonderBlocksCore.Id,{id:id,children:uniqueId=>jsxRuntime.jsxs(React__namespace.Fragment,{children:[jsxRuntime.jsx(PopoverAnchor,{anchorRef:this.updateRef,id:`${uniqueId}-anchor`,"aria-controls":uniqueId,"aria-expanded":opened?"true":"false",onClick:this.handleOpen,children:children}),this.renderPortal(uniqueId,opened)]})}),dismissEnabled&&opened&&jsxRuntime.jsx(PopoverEventListener,{onClose:this.handleClose,contentRef:this.contentRef})]})}constructor(...args){super(...args),this.state={opened:!!this.props.opened,placement:this.props.placement},this.contentRef=React__namespace.createRef(),this.maybeReturnFocus=()=>{const{anchorElement}=this.state;const{closedFocusId}=this.props;if(closedFocusId){const focusElement=ReactDOM__namespace.findDOMNode(document.getElementById(closedFocusId));focusElement?.focus();return}if(anchorElement){anchorElement.focus();}},this.handleClose=(shouldReturnFocus=true)=>{this.setState({opened:false},()=>{this.props.onClose?.();if(shouldReturnFocus){this.maybeReturnFocus();}});},this.handleOpen=()=>{if(this.props.dismissEnabled&&this.state.opened){this.handleClose(true);}else {this.setState({opened:true});}},this.updateRef=actualRef=>{if(actualRef&&this.state.anchorElement!==actualRef){this.setState({anchorElement:actualRef});}};}}Popover.defaultProps={placement:"top",showTail:true,portal:true,rootBoundary:"viewport"};
|
|
57
|
+
class Popover extends React__namespace.Component{static getDerivedStateFromProps(props,state){return {opened:typeof props.opened==="boolean"?props.opened:state.opened}}renderContent(uniqueId){const{content}=this.props;const popoverContents=typeof content==="function"?content({close:this.handleClose}):content;return React__namespace.cloneElement(popoverContents,{ref:this.contentRef,uniqueId})}renderPopper(uniqueId){const{autoUpdate,dismissEnabled,initialFocusId,placement,showTail,portal,"aria-label":ariaLabel,"aria-describedby":ariaDescribedBy,rootBoundary,viewportPadding,initialFocusDelay}=this.props;const{anchorElement}=this.state;const describedBy=ariaDescribedBy||`${uniqueId}-content`;const ariaLabelledBy=ariaLabel?undefined:`${uniqueId}-title`;const shouldAnchorExist=autoUpdate?anchorElement:true;if(!shouldAnchorExist){return null}const popperContent=jsxRuntime.jsx(wonderBlocksTooltip.TooltipPopper,{anchorElement:anchorElement,autoUpdate:autoUpdate,placement:placement,rootBoundary:rootBoundary,viewportPadding:viewportPadding,children:props=>jsxRuntime.jsx(PopoverDialog,{...props,"aria-label":ariaLabel,"aria-describedby":describedBy,"aria-labelledby":ariaLabelledBy,id:uniqueId,onUpdate:placement=>this.setState({placement}),showTail:showTail,children:this.renderContent(uniqueId)})});if(portal){return jsxRuntime.jsx(FocusManager,{anchorElement:anchorElement,initialFocusId:initialFocusId,initialFocusDelay:initialFocusDelay,onFocusOut:dismissEnabled?this.handleClose:undefined,children:popperContent})}else {return jsxRuntime.jsx(InitialFocus,{initialFocusId:initialFocusId,delay:initialFocusDelay,children:popperContent})}}getHost(){return wonderBlocksModal.maybeGetPortalMountedModalHostElement(this.state.anchorElement)||document.body}renderPortal(uniqueId,opened){if(!opened){return null}const{portal}=this.props;const popperHost=this.getHost();if(portal&&popperHost){return ReactDOM__namespace.createPortal(this.renderPopper(uniqueId),popperHost)}return this.renderPopper(uniqueId)}render(){const{children,dismissEnabled,id}=this.props;const{opened,placement}=this.state;return jsxRuntime.jsxs(PopoverContext.Provider,{value:{close:this.handleClose,placement:placement},children:[jsxRuntime.jsx(wonderBlocksCore.Id,{id:id,children:uniqueId=>jsxRuntime.jsxs(React__namespace.Fragment,{children:[jsxRuntime.jsx(PopoverAnchor,{anchorRef:this.updateRef,id:`${uniqueId}-anchor`,"aria-controls":uniqueId,"aria-expanded":opened?"true":"false",onClick:this.handleOpen,children:children}),this.renderPortal(uniqueId,opened)]})}),dismissEnabled&&opened&&jsxRuntime.jsx(PopoverEventListener,{onClose:this.handleClose,contentRef:this.contentRef})]})}constructor(...args){super(...args),this.state={opened:!!this.props.opened,placement:this.props.placement},this.contentRef=React__namespace.createRef(),this.maybeReturnFocus=()=>{const{anchorElement}=this.state;const{closedFocusId}=this.props;if(closedFocusId){const focusElement=ReactDOM__namespace.findDOMNode(document.getElementById(closedFocusId));focusElement?.focus();return}if(anchorElement){anchorElement.focus();}},this.handleClose=(shouldReturnFocus=true)=>{this.setState({opened:false},()=>{this.props.onClose?.();if(shouldReturnFocus){this.maybeReturnFocus();}});},this.handleOpen=()=>{if(this.props.dismissEnabled&&this.state.opened){this.handleClose(true);}else {this.setState({opened:true});}},this.updateRef=actualRef=>{if(actualRef&&this.state.anchorElement!==actualRef){this.setState({anchorElement:actualRef});}};}}Popover.defaultProps={placement:"top",showTail:true,portal:true,rootBoundary:"viewport"};
|
|
58
58
|
|
|
59
59
|
class CloseButton extends React__namespace.Component{render(){const{"aria-label":ariaLabel,style,testId}=this.props;return jsxRuntime.jsx(PopoverContext.Consumer,{children:({close})=>{return jsxRuntime.jsx(IconButton__default["default"],{icon:xIcon__default["default"],"aria-label":ariaLabel,onClick:close,kind:"tertiary",actionType:"neutral",style:style,testId:testId})}})}}CloseButton.defaultProps={"aria-label":"Close Popover"};
|
|
60
60
|
|
|
61
61
|
class PopoverContentCore extends React__namespace.Component{render(){const{"aria-label":ariaLabel,children,closeButtonLight,closeButtonLabel,closeButtonVisible,style,testId}=this.props;return jsxRuntime.jsxs(wonderBlocksCore.View,{testId:testId,style:[styles$1.content,style],"aria-label":ariaLabel,children:[closeButtonVisible&&jsxRuntime.jsx(CloseButton,{"aria-label":closeButtonLabel,style:[styles$1.closeButton,closeButtonLight&&wonderBlocksStyles.actionStyles.inverse],testId:`${testId||"popover"}-close-btn`}),children]})}}PopoverContentCore.defaultProps={closeButtonLight:false,closeButtonVisible:false};const styles$1=aphrodite.StyleSheet.create({content:{borderRadius:wonderBlocksTokens.border.radius.radius_040,border:`solid 1px ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.default,boxShadow:wonderBlocksTokens.boxShadow.mid,margin:0,maxWidth:wonderBlocksTokens.spacing.medium_16*18,padding:wonderBlocksTokens.spacing.large_24,overflow:"hidden",justifyContent:"center"},closeButton:{margin:0,position:"absolute",right:wonderBlocksTokens.spacing.xxxSmall_4,top:wonderBlocksTokens.spacing.xxxSmall_4,zIndex:1}});
|
|
62
62
|
|
|
63
|
-
const StyledImg=wonderBlocksCore.addStyle("img");class PopoverContent extends React__namespace.Component{componentDidMount(){const{icon,image}=this.props;if(image&&icon){throw new Error("'image' and 'icon' cannot be used at the same time. You can fix this by either removing 'image' or 'icon' from your instance.")}}validateProps({placement}){if(this.props.image&&(placement==="left"||placement==="right")){throw new Error("'image' can only be vertically placed. You can fix this by either changing `placement` to `top` or `bottom` or removing the `image` prop inside `content`.")}}render(){const{closeButtonLabel,closeButtonVisible,content,icon,image,style,title,testId,uniqueId}=this.props;return jsxRuntime.jsx(PopoverContext.Consumer,{children:({close,placement})=>{this.validateProps({close,placement});return jsxRuntime.jsxs(PopoverContentCore,{closeButtonLight:image&&placement==="top",closeButtonLabel:closeButtonLabel,closeButtonVisible:closeButtonVisible,style:style,testId:testId,children:[jsxRuntime.jsxs(wonderBlocksCore.View,{style:!!icon&&styles.withIcon,children:[this.maybeRenderImage({placement}),this.maybeRenderIcon(),jsxRuntime.jsxs(wonderBlocksCore.View,{style:styles.text,children:[jsxRuntime.jsx(wonderBlocksTypography.
|
|
63
|
+
const StyledImg=wonderBlocksCore.addStyle("img");class PopoverContent extends React__namespace.Component{componentDidMount(){const{icon,image}=this.props;if(image&&icon){throw new Error("'image' and 'icon' cannot be used at the same time. You can fix this by either removing 'image' or 'icon' from your instance.")}}validateProps({placement}){if(this.props.image&&(placement==="left"||placement==="right")){throw new Error("'image' can only be vertically placed. You can fix this by either changing `placement` to `top` or `bottom` or removing the `image` prop inside `content`.")}}render(){const{closeButtonLabel,closeButtonVisible,content,icon,image,style,title,testId,uniqueId}=this.props;return jsxRuntime.jsx(PopoverContext.Consumer,{children:({close,placement})=>{this.validateProps({close,placement});return jsxRuntime.jsxs(PopoverContentCore,{closeButtonLight:image&&placement==="top",closeButtonLabel:closeButtonLabel,closeButtonVisible:closeButtonVisible,style:style,testId:testId,children:[jsxRuntime.jsxs(wonderBlocksCore.View,{style:!!icon&&styles.withIcon,children:[this.maybeRenderImage({placement}),this.maybeRenderIcon(),jsxRuntime.jsxs(wonderBlocksCore.View,{style:styles.text,children:[jsxRuntime.jsx(wonderBlocksTypography.Heading,{size:"medium",id:`${uniqueId}-title`,style:styles.title,children:title}),jsxRuntime.jsx(wonderBlocksTypography.BodyText,{tag:"span",id:`${uniqueId}-content`,children:content})]})]}),this.maybeRenderActions(close)]})}})}constructor(...args){super(...args),this.maybeRenderImage=({placement})=>{const{image}=this.props;if(!image){return null}return jsxRuntime.jsx(wonderBlocksCore.View,{style:[styles.image,placement==="bottom"&&styles.imageToBottom],children:image})},this.maybeRenderIcon=()=>{const{icon,iconAlt}=this.props;if(!icon){return null}return jsxRuntime.jsx(wonderBlocksCore.View,{style:styles.iconContainer,children:typeof icon!=="string"?icon:jsxRuntime.jsx(StyledImg,{src:icon,style:styles.icon,alt:iconAlt||""})})},this.maybeRenderActions=close=>{const{actions}=this.props;if(!actions){return null}return jsxRuntime.jsx(wonderBlocksCore.View,{style:styles.actions,children:typeof actions==="function"?actions({close:close}):actions})};}}PopoverContent.defaultProps={closeButtonVisible:false};const styles=aphrodite.StyleSheet.create({actions:{marginTop:wonderBlocksTokens.spacing.large_24,flexDirection:"row",alignItems:"center",justifyContent:"flex-end"},text:{justifyContent:"center"},title:{marginBottom:wonderBlocksTokens.spacing.xSmall_8},iconContainer:{alignItems:"center",justifyContent:"center",height:wonderBlocksTokens.spacing.xxxLarge_64,width:wonderBlocksTokens.spacing.xxxLarge_64,minWidth:wonderBlocksTokens.spacing.xxxLarge_64,marginRight:wonderBlocksTokens.spacing.medium_16,overflow:"hidden"},icon:{width:"100%"},withIcon:{flexDirection:"row"},image:{marginBottom:wonderBlocksTokens.spacing.large_24,marginLeft:-wonderBlocksTokens.spacing.large_24,marginRight:-wonderBlocksTokens.spacing.large_24,marginTop:-wonderBlocksTokens.spacing.large_24,width:`calc(100% + ${wonderBlocksTokens.spacing.large_24*2}px)`},imageToBottom:{marginBottom:-wonderBlocksTokens.spacing.large_24,marginTop:wonderBlocksTokens.spacing.large_24,order:1}});
|
|
64
64
|
|
|
65
65
|
exports.Popover = Popover;
|
|
66
66
|
exports.PopoverContent = PopoverContent;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "6.1
|
|
6
|
+
"version": "6.2.1",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
"types": "dist/index.d.ts",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@khanacademy/wonder-blocks-core": "12.4.3",
|
|
24
|
-
"@khanacademy/wonder-blocks-icon-button": "11.2.
|
|
25
|
-
"@khanacademy/wonder-blocks-modal": "8.6.
|
|
26
|
-
"@khanacademy/wonder-blocks-styles": "0.2.
|
|
27
|
-
"@khanacademy/wonder-blocks-tokens": "16.
|
|
28
|
-
"@khanacademy/wonder-blocks-tooltip": "4.1.
|
|
29
|
-
"@khanacademy/wonder-blocks-typography": "4.
|
|
24
|
+
"@khanacademy/wonder-blocks-icon-button": "11.2.1",
|
|
25
|
+
"@khanacademy/wonder-blocks-modal": "8.6.2",
|
|
26
|
+
"@khanacademy/wonder-blocks-styles": "0.2.41",
|
|
27
|
+
"@khanacademy/wonder-blocks-tokens": "16.2.0",
|
|
28
|
+
"@khanacademy/wonder-blocks-tooltip": "4.1.71",
|
|
29
|
+
"@khanacademy/wonder-blocks-typography": "4.3.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"@phosphor-icons/core": "^2.0.2",
|