Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F102314963
usePopper.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Feb 19, 10:20
Size
5 KB
Mime Type
text/x-java
Expires
Fri, Feb 21, 10:20 (6 h, 10 m)
Engine
blob
Format
Raw Data
Handle
24329274
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
usePopper.js
View Options
const
_excluded
=
[
"enabled"
,
"placement"
,
"strategy"
,
"modifiers"
];
function
_objectWithoutPropertiesLoose
(
source
,
excluded
)
{
if
(
source
==
null
)
return
{};
var
target
=
{};
var
sourceKeys
=
Object
.
keys
(
source
);
var
key
,
i
;
for
(
i
=
0
;
i
<
sourceKeys
.
length
;
i
++
)
{
key
=
sourceKeys
[
i
];
if
(
excluded
.
indexOf
(
key
)
>=
0
)
continue
;
target
[
key
]
=
source
[
key
];
}
return
target
;
}
import
{
useCallback
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
'react'
;
import
{
dequal
}
from
'dequal'
;
import
useSafeState
from
'@restart/hooks/useSafeState'
;
import
{
createPopper
}
from
'./popper'
;
const
disabledApplyStylesModifier
=
{
name
:
'applyStyles'
,
enabled
:
false
,
phase
:
'afterWrite'
,
fn
:
()
=>
undefined
};
// until docjs supports type exports...
const
ariaDescribedByModifier
=
{
name
:
'ariaDescribedBy'
,
enabled
:
true
,
phase
:
'afterWrite'
,
effect
:
({
state
})
=>
()
=>
{
const
{
reference
,
popper
}
=
state
.
elements
;
if
(
'removeAttribute'
in
reference
)
{
const
ids
=
(
reference
.
getAttribute
(
'aria-describedby'
)
||
''
).
split
(
','
).
filter
(
id
=>
id
.
trim
()
!==
popper
.
id
);
if
(
!
ids
.
length
)
reference
.
removeAttribute
(
'aria-describedby'
);
else
reference
.
setAttribute
(
'aria-describedby'
,
ids
.
join
(
','
));
}
},
fn
:
({
state
})
=>
{
var
_popper$getAttribute
;
const
{
popper
,
reference
}
=
state
.
elements
;
const
role
=
(
_popper$getAttribute
=
popper
.
getAttribute
(
'role'
))
==
null
?
void
0
:
_popper$getAttribute
.
toLowerCase
();
if
(
popper
.
id
&&
role
===
'tooltip'
&&
'setAttribute'
in
reference
)
{
const
ids
=
reference
.
getAttribute
(
'aria-describedby'
);
if
(
ids
&&
ids
.
split
(
','
).
indexOf
(
popper
.
id
)
!==
-
1
)
{
return
;
}
reference
.
setAttribute
(
'aria-describedby'
,
ids
?
`
$
{
ids
},
$
{
popper
.
id
}
`
:
popper
.
id
);
}
}
};
const
EMPTY_MODIFIERS
=
[];
/**
* Position an element relative some reference element using Popper.js
*
* @param referenceElement
* @param popperElement
* @param {object} options
* @param {object=} options.modifiers Popper.js modifiers
* @param {boolean=} options.enabled toggle the popper functionality on/off
* @param {string=} options.placement The popper element placement relative to the reference element
* @param {string=} options.strategy the positioning strategy
* @param {function=} options.onCreate called when the popper is created
* @param {function=} options.onUpdate called when the popper is updated
*
* @returns {UsePopperState} The popper state
*/
function
usePopper
(
referenceElement
,
popperElement
,
_ref
=
{})
{
let
{
enabled
=
true
,
placement
=
'bottom'
,
strategy
=
'absolute'
,
modifiers
=
EMPTY_MODIFIERS
}
=
_ref
,
config
=
_objectWithoutPropertiesLoose
(
_ref
,
_excluded
);
const
prevModifiers
=
useRef
(
modifiers
);
const
popperInstanceRef
=
useRef
();
const
update
=
useCallback
(()
=>
{
var
_popperInstanceRef$cu
;
(
_popperInstanceRef$cu
=
popperInstanceRef
.
current
)
==
null
?
void
0
:
_popperInstanceRef$cu
.
update
();
},
[]);
const
forceUpdate
=
useCallback
(()
=>
{
var
_popperInstanceRef$cu2
;
(
_popperInstanceRef$cu2
=
popperInstanceRef
.
current
)
==
null
?
void
0
:
_popperInstanceRef$cu2
.
forceUpdate
();
},
[]);
const
[
popperState
,
setState
]
=
useSafeState
(
useState
({
placement
,
update
,
forceUpdate
,
attributes
:
{},
styles
:
{
popper
:
{},
arrow
:
{}
}
}));
const
updateModifier
=
useMemo
(()
=>
({
name
:
'updateStateModifier'
,
enabled
:
true
,
phase
:
'write'
,
requires
:
[
'computeStyles'
],
fn
:
({
state
})
=>
{
const
styles
=
{};
const
attributes
=
{};
Object
.
keys
(
state
.
elements
).
forEach
(
element
=>
{
styles
[
element
]
=
state
.
styles
[
element
];
attributes
[
element
]
=
state
.
attributes
[
element
];
});
setState
({
state
,
styles
,
attributes
,
update
,
forceUpdate
,
placement
:
state
.
placement
});
}
}),
[
update
,
forceUpdate
,
setState
]);
const
nextModifiers
=
useMemo
(()
=>
{
if
(
!
dequal
(
prevModifiers
.
current
,
modifiers
))
{
prevModifiers
.
current
=
modifiers
;
}
return
prevModifiers
.
current
;
},
[
modifiers
]);
useEffect
(()
=>
{
if
(
!
popperInstanceRef
.
current
||
!
enabled
)
return
;
popperInstanceRef
.
current
.
setOptions
({
placement
,
strategy
,
modifiers
:
[...
nextModifiers
,
updateModifier
,
disabledApplyStylesModifier
]
});
},
[
strategy
,
placement
,
updateModifier
,
enabled
,
nextModifiers
]);
useEffect
(()
=>
{
if
(
!
enabled
||
referenceElement
==
null
||
popperElement
==
null
)
{
return
undefined
;
}
popperInstanceRef
.
current
=
createPopper
(
referenceElement
,
popperElement
,
Object
.
assign
({},
config
,
{
placement
,
strategy
,
modifiers
:
[...
nextModifiers
,
ariaDescribedByModifier
,
updateModifier
]
}));
return
()
=>
{
if
(
popperInstanceRef
.
current
!=
null
)
{
popperInstanceRef
.
current
.
destroy
();
popperInstanceRef
.
current
=
undefined
;
setState
(
s
=>
Object
.
assign
({},
s
,
{
attributes
:
{},
styles
:
{
popper
:
{}
}
}));
}
};
// This is only run once to _create_ the popper
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
enabled
,
referenceElement
,
popperElement
]);
return
popperState
;
}
export
default
usePopper
;
Event Timeline
Log In to Comment