Skip to content

Commit 8f4455d

Browse files
committed
migrate Popup
1 parent 71a016f commit 8f4455d

File tree

9 files changed

+320
-230
lines changed

9 files changed

+320
-230
lines changed

src/addons/Portal/Portal.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ export interface StrictPortalProps {
9292

9393
/** Element to be rendered in-place where the portal is defined. */
9494
trigger?: React.ReactNode
95+
96+
/** Called with a ref to the trigger node. */
97+
triggerRef?: React.Ref<any>
9598
}
9699

97100
declare class Portal extends React.Component<PortalProps> {

src/addons/Portal/Portal.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import PropTypes from 'prop-types'
55
import React from 'react'
66

77
import {
8+
customPropTypes,
89
doesNodeContainClick,
910
makeDebugger,
1011
useAutoControlledValue,
11-
useMergedRefs,
1212
} from '../../lib'
13-
import validateTrigger from './utils/validateTrigger'
13+
import useTrigger from './utils/useTrigger'
1414
import PortalInner from './PortalInner'
1515

1616
const debug = makeDebugger('portal')
@@ -38,22 +38,16 @@ function Portal(props) {
3838
openOnTriggerClick,
3939
openOnTriggerFocus,
4040
openOnTriggerMouseEnter,
41-
trigger,
4241
} = props
4342

44-
/* istanbul ignore else */
45-
if (process.env.NODE_ENV !== 'production') {
46-
validateTrigger(trigger)
47-
}
48-
4943
const [open, setOpen] = useAutoControlledValue({
5044
state: props.open,
5145
defaultState: props.defaultOpen,
5246
initialState: false,
5347
})
5448

5549
const contentRef = React.useRef()
56-
const triggerRef = useMergedRefs(trigger?.ref, React.useRef())
50+
const [triggerRef, trigger] = useTrigger(props.trigger, props.triggerRef)
5751

5852
const mouseEnterTimer = React.useRef()
5953
const mouseLeaveTimer = React.useRef()
@@ -379,6 +373,9 @@ Portal.propTypes = {
379373

380374
/** Element to be rendered in-place where the portal is defined. */
381375
trigger: PropTypes.node,
376+
377+
/** Called with a ref to the trigger node. */
378+
triggerRef: customPropTypes.ref,
382379
}
383380

384381
Portal.defaultProps = {

src/addons/Portal/utils/useTrigger.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react'
2+
3+
import { useMergedRefs } from '../../../lib'
4+
import validateTrigger from './validateTrigger'
5+
6+
/**
7+
* @param {React.ReactNode} trigger
8+
* @param {React.Ref} triggerRef
9+
*/
10+
function useTrigger(trigger, triggerRef) {
11+
const ref = useMergedRefs(trigger?.ref, triggerRef)
12+
13+
if (trigger) {
14+
/* istanbul ignore else */
15+
if (process.env.NODE_ENV !== 'production') {
16+
validateTrigger(trigger)
17+
}
18+
19+
return [ref, React.cloneElement(trigger, { ref })]
20+
}
21+
22+
return [ref, null]
23+
}
24+
25+
export default useTrigger

src/addons/Portal/utils/validateTrigger.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import * as ReactIs from 'react-is'
55
* Asserts that a passed element can be used cloned a props will be applied properly.
66
*/
77
export default function validateTrigger(element) {
8-
if (element) {
9-
React.Children.only(element)
8+
React.Children.only(element)
109

11-
if (ReactIs.isFragment(element)) {
12-
throw new Error('An "React.Fragment" cannot be used as a `trigger`.')
13-
}
10+
if (ReactIs.isFragment(element)) {
11+
throw new Error('An "React.Fragment" cannot be used as a `trigger`.')
1412
}
1513
}

src/lib/hooks/usePrevious.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as React from 'react'
2+
3+
/**
4+
* Hook keeping track of a given value from a previous execution of the component the Hook is used in.
5+
*
6+
* @see https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
7+
*/
8+
function usePrevious(value) {
9+
const ref = React.useRef()
10+
11+
React.useEffect(() => {
12+
ref.current = value
13+
})
14+
15+
return ref.current
16+
}
17+
18+
export default usePrevious

src/lib/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,7 @@ export { makeDebugger }
4848

4949
export useAutoControlledValue from './hooks/useAutoControlledValue'
5050
export useClassNamesOnNode from './hooks/useClassNamesOnNode'
51-
export useMergedRefs from './hooks/useMergedRefs'
5251
export useEventCallback from './hooks/useEventCallback'
52+
export useIsomorphicLayoutEffect from './hooks/useIsomorphicLayoutEffect'
53+
export useMergedRefs from './hooks/useMergedRefs'
54+
export usePrevious from './hooks/usePrevious'

0 commit comments

Comments
 (0)