11import { InputType , StyleVariables } from "helpers/Constants" ;
22import { dbTrim , c , getLabelHeader } from "helpers/StylesHelper" ;
33import AdjustmentsIcon from "components/img/AdjustmentsIcon" ;
4- import React , { FocusEventHandler , useEffect , useState } from "react" ;
5- import { usePopper } from "react-popper " ;
4+ import React , { FocusEventHandler , useState } from "react" ;
5+ import Popper from "@mui/material/Popper " ;
66import header_action_button_section from "components/headerActions/HeaderActionButtonSection" ;
77import header_action_types_section from "components/headerActions/HeaderActiontypesSection" ;
88import { ColumnSettingsModal } from "components/modals/columnSettings/ColumnSettingsModal" ;
9+ import { PopperTypesStyleModifiers } from "components/styles/PopperStyles" ;
910import { TableColumn } from "cdm/FolderModel" ;
1011import { HeaderActionResponse } from "cdm/HeaderActionModel" ;
1112import { HeaderMenuProps } from "cdm/HeaderModel" ;
13+ import Box from "@mui/material/Box" ;
14+ import ClickAwayListener from "@mui/material/ClickAwayListener" ;
1215
1316const HeaderMenu = ( headerMenuProps : HeaderMenuProps ) => {
1417 const { table, column } = headerMenuProps . headerProps ;
18+
1519 const [ columnsInfo , columnActions ] = table . options . meta . tableState . columns (
1620 ( state ) => [ state . info , state . actions ]
1721 ) ;
@@ -23,69 +27,51 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
2327 ) ;
2428
2529 /** Header props */
26- const {
27- propertyIcon,
28- expanded,
29- setExpanded,
30- created,
31- referenceElement,
32- labelState,
33- setLabelState,
34- } = headerMenuProps ;
30+ const { propertyIcon, menuEl, setMenuEl, labelState, setLabelState } =
31+ headerMenuProps ;
3532
3633 const { key, isMetadata, input } = column . columnDef as TableColumn ;
3734 /** Column values */
3835 const [ keyState , setkeyState ] = useState ( dbTrim ( key ) ) ;
39- const [ popperElement , setPopperElement ] = useState ( null ) ;
4036 const [ inputRef , setInputRef ] = useState ( null ) ;
41- const { styles, attributes } = usePopper ( referenceElement , popperElement , {
42- placement : "bottom" ,
43- strategy : "absolute" ,
44- } ) ;
45- // Manage type of data
46- const [ typeReferenceElement , setTypeReferenceElement ] = useState ( null ) ;
47- const [ typePopperElement , setTypePopperElement ] = useState ( null ) ;
48- const [ showType , setShowType ] = useState ( false ) ;
37+
38+ // Manage menu Popper
39+ const openMenu = Boolean ( menuEl ) ;
40+ const idMenu = openMenu ? `header-menu-popper` : undefined ;
41+
42+ // Manage type Popper
43+ const [ typesEl , setTypesEl ] = useState < null | HTMLElement > ( null ) ;
44+ const [ typesTimeout , setTypesTimeout ] = useState ( null ) ;
45+
46+ const isTypesShown = Boolean ( typesEl ) ;
47+ const idTypes = isTypesShown ? `types-menu-popper` : undefined ;
4948
5049 // Manage errors
5150 const [ labelStateInvalid , setLabelStateInvalid ] = useState ( false ) ;
5251
53- /** Event driven actions */
54- useEffect ( ( ) => {
55- // Throw event if created changed to expand or collapse the menu
56- if ( created ) {
57- setExpanded ( true ) ;
58- }
59- } , [ created ] ) ;
60-
6152 /**
6253 * Array of action buttons asociated to the header
6354 */
6455 let headerActionResponse : HeaderActionResponse = {
6556 buttons : [ ] ,
6657 headerMenuProps : headerMenuProps ,
6758 hooks : {
68- setExpanded : setExpanded ,
59+ setMenuEl : setMenuEl ,
60+ setTypesEl : setTypesEl ,
6961 keyState : keyState ,
7062 setKeyState : setkeyState ,
71- setShowType : setShowType ,
7263 } ,
7364 } ;
7465 const headerButtons =
7566 header_action_button_section . run ( headerActionResponse ) . buttons ;
7667
77- /**
78- * Array of type headers available to change the data type of the column
79- */
68+ // / **
69+ // * Array of type headers available to change the data type of the column
70+ // */
8071 headerActionResponse . buttons = [ ] ;
8172 const typesButtons =
8273 header_action_types_section . run ( headerActionResponse ) . buttons ;
8374
84- const typePopper = usePopper ( typeReferenceElement , typePopperElement , {
85- placement : "right" ,
86- strategy : "fixed" ,
87- } ) ;
88-
8975 function persistLabelChange ( ) {
9076 // Update state of altered column
9177 columnActions . alterColumnLabel ( column . columnDef as TableColumn , labelState ) ;
@@ -119,22 +105,10 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
119105 } ;
120106
121107 return (
122- < div >
123- { expanded && (
124- < div className = "overlay" onClick = { ( ) => setExpanded ( false ) } />
125- ) }
126- { expanded && (
127- < div
128- ref = { setPopperElement }
129- style = { { ...styles . popper , zIndex : 3 } }
130- { ...attributes . popper }
131- >
132- < div
133- className = { `menu ${ c ( "popper" ) } ` }
134- style = { {
135- width : 240 ,
136- } }
137- >
108+ < Popper id = { idMenu } open = { openMenu } anchorEl = { menuEl } key = { idMenu } >
109+ < ClickAwayListener onClickAway = { ( ) => setMenuEl ( null ) } >
110+ < Box >
111+ < div className = { `menu ${ c ( "popper" ) } ` } >
138112 { /** Edit header label section */ }
139113 { ! isMetadata && (
140114 < >
@@ -177,9 +151,17 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
177151 < div style = { { padding : "4px 0px" } } >
178152 < div
179153 className = "menu-item sort-button"
180- onMouseEnter = { ( ) => setShowType ( true ) }
181- onMouseLeave = { ( ) => setShowType ( false ) }
182- ref = { setTypeReferenceElement }
154+ onMouseOver = { async ( event ) => {
155+ setTypesEl ( event . currentTarget ) ;
156+ } }
157+ onMouseLeave = { ( ) => {
158+ const timeoutId = setTimeout ( ( ) => {
159+ setTypesEl ( null ) ;
160+ setTypesTimeout ( null ) ;
161+ // timeout until event is triggered after user has stopped typing
162+ } , 250 ) ;
163+ setTypesTimeout ( timeoutId ) ;
164+ } }
183165 >
184166 < span className = "svg-icon svg-text icon-margin" >
185167 { propertyIcon }
@@ -188,24 +170,29 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
188170 { getLabelHeader ( input ) }
189171 </ span >
190172 </ div >
191- { showType && (
192- < div
193- className = { `menu ${ c ( "popper" ) } ` }
194- ref = { setTypePopperElement }
195- onMouseEnter = { ( ) => setShowType ( true ) }
196- onMouseLeave = { ( ) => setShowType ( false ) }
197- { ...typePopper . attributes . popper }
198- style = { {
199- ...typePopper . styles . popper ,
200- width : 200 ,
201- zIndex : 4 ,
202- padding : "4px 0px" ,
203- } }
204- >
173+ < Popper
174+ id = { idTypes }
175+ open = { isTypesShown }
176+ anchorEl = { typesEl }
177+ placement = "right"
178+ disablePortal = { false }
179+ key = { idTypes }
180+ modifiers = { PopperTypesStyleModifiers ( ) }
181+ onMouseOver = { ( ) => {
182+ if ( typesTimeout ) {
183+ clearTimeout ( typesTimeout ) ;
184+ setTypesTimeout ( null ) ;
185+ }
186+ } }
187+ onMouseLeave = { async ( ) => {
188+ setTypesEl ( null ) ;
189+ } }
190+ >
191+ < Box className = { `menu ${ c ( "popper" ) } ` } >
205192 { /** Childs of typesButtons */ }
206193 { typesButtons }
207- </ div >
208- ) }
194+ </ Box >
195+ </ Popper >
209196 </ div >
210197 </ >
211198 ) }
@@ -241,7 +228,7 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
241228 view : table . options . meta . view ,
242229 headerMenuProps : headerMenuProps ,
243230 } ) . open ( ) ;
244- setExpanded ( false ) ;
231+ setMenuEl ( null ) ;
245232 } }
246233 >
247234 < span className = "svg-icon svg-text icon-margin" >
@@ -253,9 +240,9 @@ const HeaderMenu = (headerMenuProps: HeaderMenuProps) => {
253240 </ div >
254241 ) }
255242 </ div >
256- </ div >
257- ) }
258- </ div >
243+ </ Box >
244+ </ ClickAwayListener >
245+ </ Popper >
259246 ) ;
260247} ;
261248
0 commit comments