react-animated-select 0.5.2 → 0.6.0
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/README.md +17 -8
- package/dist/index.cjs.js +12 -10
- package/dist/index.css +1 -1
- package/dist/index.es.js +1297 -1132
- package/index.d.ts +5 -1
- package/package.json +8 -4
- package/.github/workflows/publish.yml +0 -32
- package/demo/README.md +0 -16
- package/demo/eslint.config.js +0 -29
- package/demo/index.html +0 -13
- package/demo/package-lock.json +0 -3619
- package/demo/package.json +0 -35
- package/demo/public/vite.svg +0 -1
- package/demo/src/App.tsx +0 -437
- package/demo/src/main.jsx +0 -9
- package/demo/src/rac.css +0 -746
- package/demo/src/shake.js +0 -11
- package/demo/src/slideDown.jsx +0 -35
- package/demo/vite.config.js +0 -7
- package/src/animated.jsx +0 -80
- package/src/getText.jsx +0 -11
- package/src/icons.jsx +0 -43
- package/src/index.js +0 -5
- package/src/makeId.jsx +0 -21
- package/src/optgroup.jsx +0 -36
- package/src/option.jsx +0 -50
- package/src/options.jsx +0 -197
- package/src/select.css +0 -356
- package/src/select.jsx +0 -339
- package/src/selectContext.js +0 -3
- package/src/selectJSX.jsx +0 -265
- package/src/slideDown.jsx +0 -36
- package/src/slideLeft.jsx +0 -41
- package/src/useSelect.jsx +0 -186
- package/src/useSelectLogic.jsx +0 -413
- package/vite.config.js +0 -27
package/demo/src/shake.js
DELETED
package/demo/src/slideDown.jsx
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import {CSSTransition} from 'react-transition-group'
|
|
2
|
-
import {useRef} from 'react'
|
|
3
|
-
|
|
4
|
-
function SlideDown({visibility, children, duration = 300}) {
|
|
5
|
-
const nodeRef = useRef(null)
|
|
6
|
-
|
|
7
|
-
return(
|
|
8
|
-
<CSSTransition
|
|
9
|
-
in={visibility}
|
|
10
|
-
timeout={300}
|
|
11
|
-
classNames='slideDown'
|
|
12
|
-
unmountOnExit
|
|
13
|
-
nodeRef={nodeRef}
|
|
14
|
-
onEnter={() => (nodeRef.current.style.height = '0px')}
|
|
15
|
-
onEntering={() => (nodeRef.current.style.height = nodeRef.current.scrollHeight + 'px')}
|
|
16
|
-
onEntered={() => (nodeRef.current.style.height = 'auto')}
|
|
17
|
-
onExit={() => (nodeRef.current.style.height = nodeRef.current.scrollHeight + 'px')}
|
|
18
|
-
onExiting={() => (nodeRef.current.style.height = '0px')}
|
|
19
|
-
>
|
|
20
|
-
<div
|
|
21
|
-
ref={nodeRef}
|
|
22
|
-
style={{
|
|
23
|
-
overflow: 'hidden',
|
|
24
|
-
transition: `height ${duration}ms ease`
|
|
25
|
-
}}
|
|
26
|
-
className='slideDown-enter-done'
|
|
27
|
-
tabIndex={-1}
|
|
28
|
-
>
|
|
29
|
-
{children}
|
|
30
|
-
</div>
|
|
31
|
-
</CSSTransition>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export default SlideDown
|
package/demo/vite.config.js
DELETED
package/src/animated.jsx
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import {useRef} from 'react'
|
|
2
|
-
import {CSSTransition} from 'react-transition-group'
|
|
3
|
-
|
|
4
|
-
const Animated = ({children, duration, widthMode = false, ...props}) => {
|
|
5
|
-
const nodeRef = useRef(null)
|
|
6
|
-
return (
|
|
7
|
-
<CSSTransition
|
|
8
|
-
nodeRef={nodeRef}
|
|
9
|
-
timeout={duration}
|
|
10
|
-
classNames='rac-slide-left'
|
|
11
|
-
{...props}
|
|
12
|
-
onEnter={() => {
|
|
13
|
-
const el = nodeRef.current
|
|
14
|
-
if (widthMode) {
|
|
15
|
-
el.style.width = '0px'
|
|
16
|
-
} else {
|
|
17
|
-
el.style.height = '0px'
|
|
18
|
-
el.style.transform = 'translateY(-10px)'
|
|
19
|
-
}
|
|
20
|
-
el.style.opacity = '0'
|
|
21
|
-
}}
|
|
22
|
-
onEntering={() => {
|
|
23
|
-
const el = nodeRef.current
|
|
24
|
-
el.offsetHeight
|
|
25
|
-
if (widthMode) {
|
|
26
|
-
el.style.width = el.scrollWidth + 'px'
|
|
27
|
-
} else {
|
|
28
|
-
el.style.height = el.scrollHeight + 'px'
|
|
29
|
-
el.style.transform = 'translateY(0)'
|
|
30
|
-
}
|
|
31
|
-
el.style.opacity = '1'
|
|
32
|
-
}}
|
|
33
|
-
onEntered={() => {
|
|
34
|
-
const el = nodeRef.current
|
|
35
|
-
el.style.width = widthMode ? 'auto' : ''
|
|
36
|
-
el.style.height = widthMode ? '' : 'auto'
|
|
37
|
-
el.style.opacity = '1'
|
|
38
|
-
el.style.transform = ''
|
|
39
|
-
}}
|
|
40
|
-
onExit={() => {
|
|
41
|
-
const el = nodeRef.current
|
|
42
|
-
if (widthMode) {
|
|
43
|
-
el.style.width = el.offsetWidth + 'px'
|
|
44
|
-
} else {
|
|
45
|
-
el.style.height = el.offsetHeight + 'px'
|
|
46
|
-
el.style.position = 'absolute'
|
|
47
|
-
}
|
|
48
|
-
el.style.opacity = '1'
|
|
49
|
-
}}
|
|
50
|
-
onExiting={() => {
|
|
51
|
-
const el = nodeRef.current
|
|
52
|
-
if (widthMode) {
|
|
53
|
-
el.style.width = '0px'
|
|
54
|
-
} else {
|
|
55
|
-
el.style.height = '0px'
|
|
56
|
-
el.style.transform = 'translateY(10px)'
|
|
57
|
-
}
|
|
58
|
-
el.style.opacity = '0'
|
|
59
|
-
}}
|
|
60
|
-
>
|
|
61
|
-
<div
|
|
62
|
-
ref={nodeRef}
|
|
63
|
-
style={{
|
|
64
|
-
display: 'flex',
|
|
65
|
-
alignItems: 'center',
|
|
66
|
-
height: '100%',
|
|
67
|
-
overflow: 'hidden',
|
|
68
|
-
whiteSpace: 'nowrap',
|
|
69
|
-
transition: `all ${duration}ms ease`,
|
|
70
|
-
top: 0,
|
|
71
|
-
left: 0
|
|
72
|
-
}}
|
|
73
|
-
>
|
|
74
|
-
{children}
|
|
75
|
-
</div>
|
|
76
|
-
</CSSTransition>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export default Animated
|
package/src/getText.jsx
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
|
|
3
|
-
const getText = (children) => {
|
|
4
|
-
if (!children) return ''
|
|
5
|
-
if (typeof children === 'string' || typeof children === 'number') return String(children)
|
|
6
|
-
if (Array.isArray(children)) return children.map(getText).join(' ').replace(/\s+/g, ' ').trim()
|
|
7
|
-
if (React.isValidElement(children)) return getText(children.props.children)
|
|
8
|
-
return ''
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export default getText
|
package/src/icons.jsx
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
export const XMarkIcon = ({className = '', ...props}) => (
|
|
2
|
-
<svg
|
|
3
|
-
className={className}
|
|
4
|
-
role='button'
|
|
5
|
-
aria-label='Clear selection'
|
|
6
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
-
viewBox="0 0 320 512"
|
|
8
|
-
width="1em"
|
|
9
|
-
height="1em"
|
|
10
|
-
fill="currentColor"
|
|
11
|
-
{...props}
|
|
12
|
-
>
|
|
13
|
-
<path d="M310.6 361.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L160 301.3 54.6 406.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L114.7 256 9.4 150.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 210.7 265.4 105.4c12.5-12.5 32.8-12.5 45.3 0s12.5 32.8 0 45.3L205.3 256l105.3 105.4z"/>
|
|
14
|
-
</svg>
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
export const ArrowUpIcon = ({className = '', ...props}) => (
|
|
18
|
-
<svg
|
|
19
|
-
className={className}
|
|
20
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
21
|
-
viewBox="0 0 448 512"
|
|
22
|
-
width="1em"
|
|
23
|
-
height="1em"
|
|
24
|
-
fill="currentColor"
|
|
25
|
-
{...props}
|
|
26
|
-
>
|
|
27
|
-
<path d="M34.9 289.5l175.9-175.8c9.4-9.4 24.6-9.4 33.9 0L420.1 289.5c15.1 15.1 4.4 41-17 41H51.9c-21.4 0-32.1-25.9-17-41z"/>
|
|
28
|
-
</svg>
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
export const CheckmarkIcon = ({className = '', ...props}) => (
|
|
32
|
-
<svg
|
|
33
|
-
className={className}
|
|
34
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
35
|
-
viewBox="0 0 24 24"
|
|
36
|
-
width="1em"
|
|
37
|
-
height="1em"
|
|
38
|
-
fill="currentColor"
|
|
39
|
-
{...props}
|
|
40
|
-
>
|
|
41
|
-
<path d="M20.285 6.708a1 1 0 0 0-1.414-1.416l-9.192 9.192-4.243-4.244a1 1 0 1 0-1.414 1.416l5 5a1 1 0 0 0 1.414 0l9.849-9.948z"/>
|
|
42
|
-
</svg>
|
|
43
|
-
)
|
package/src/index.js
DELETED
package/src/makeId.jsx
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// if user does not provide a unique identifier, a unique ID is generated based on value, filtering out unwanted characters
|
|
2
|
-
export const makeId = (str, fallback = 'invalid-option', seed = '') => {
|
|
3
|
-
const safeSeed = seed ? seed.replace(/:/g, '') : ''
|
|
4
|
-
|
|
5
|
-
if (typeof str !== 'string' || !str.trim()) {
|
|
6
|
-
return safeSeed ? `${fallback}-${safeSeed}` : `${fallback}-${Math.random().toString(36).slice(2, 8)}`
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const cleaned = str
|
|
10
|
-
.normalize('NFKD')
|
|
11
|
-
.replace(/[\u0300-\u036f]/g, '')
|
|
12
|
-
.replace(/\s+/g, '-')
|
|
13
|
-
.replace(/[^\p{L}\p{N}-]+/gu, '')
|
|
14
|
-
.toLowerCase()
|
|
15
|
-
|
|
16
|
-
if (!cleaned) {
|
|
17
|
-
return safeSeed ? `${fallback}-${safeSeed}` : `${fallback}-${Math.random().toString(36).slice(2, 8)}`
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return cleaned || `${fallback}-${Math.random().toString(36).slice(2, 8)}`
|
|
21
|
-
}
|
package/src/optgroup.jsx
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {useContext, useEffect, useMemo, createContext} from 'react'
|
|
2
|
-
import {SelectContext} from './selectContext'
|
|
3
|
-
import {makeId} from './makeId'
|
|
4
|
-
|
|
5
|
-
export const GroupContext = createContext(null)
|
|
6
|
-
|
|
7
|
-
export default function OptGroup({children, name, label, value, id, emptyGroupText = 'Empty group'}) {
|
|
8
|
-
const ctx = useContext(SelectContext)
|
|
9
|
-
|
|
10
|
-
const groupName = useMemo(() => {
|
|
11
|
-
const val = name ?? label ?? value ?? id
|
|
12
|
-
return (val !== undefined && val !== null && val !== '') ? String(val) : emptyGroupText
|
|
13
|
-
}, [name, label, value, id, emptyGroupText])
|
|
14
|
-
|
|
15
|
-
const groupId = useMemo(() => `group-marker-${makeId(groupName)}`, [groupName])
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
if (!ctx) return
|
|
19
|
-
|
|
20
|
-
const groupMarker = {
|
|
21
|
-
id: groupId,
|
|
22
|
-
group: groupName,
|
|
23
|
-
isGroupMarker: true,
|
|
24
|
-
disabled: true
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
ctx.registerOption(groupMarker)
|
|
28
|
-
return () => ctx.unregisterOption(groupId)
|
|
29
|
-
}, [ctx.registerOption, ctx.unregisterOption, groupId, groupName])
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<GroupContext.Provider value={groupName}>
|
|
33
|
-
{children}
|
|
34
|
-
</GroupContext.Provider>
|
|
35
|
-
)
|
|
36
|
-
}
|
package/src/option.jsx
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import {useEffect, useContext, useMemo, useId} from 'react'
|
|
2
|
-
import {SelectContext} from './selectContext'
|
|
3
|
-
import {GroupContext} from './optgroup'
|
|
4
|
-
import getText from './getText'
|
|
5
|
-
|
|
6
|
-
export default function Option({value, id, className, children, disabled, group: manualGroup}) {
|
|
7
|
-
const ctx = useContext(SelectContext)
|
|
8
|
-
const contextGroup = useContext(GroupContext)
|
|
9
|
-
|
|
10
|
-
const registerOption = ctx?.registerOption;
|
|
11
|
-
const unregisterOption = ctx?.unregisterOption;
|
|
12
|
-
|
|
13
|
-
const uniqueId = useId()
|
|
14
|
-
const stableId = useMemo(() => {
|
|
15
|
-
return id ? String(id) : uniqueId.replace(/:/g, '')
|
|
16
|
-
}, [id, uniqueId])
|
|
17
|
-
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (!registerOption) return
|
|
20
|
-
|
|
21
|
-
const textFallback = getText(children)
|
|
22
|
-
const hasJsx = children !== undefined && children !== null
|
|
23
|
-
let finalLabel = ''
|
|
24
|
-
|
|
25
|
-
if (textFallback) {
|
|
26
|
-
finalLabel = textFallback
|
|
27
|
-
} else if (id !== undefined && id !== null && id !== '') {
|
|
28
|
-
finalLabel = String(id)
|
|
29
|
-
} else if (value !== undefined && value !== null && value !== '') {
|
|
30
|
-
finalLabel = String(value)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const option = {
|
|
34
|
-
id: stableId,
|
|
35
|
-
value: value !== undefined ? value : textFallback,
|
|
36
|
-
label: finalLabel,
|
|
37
|
-
jsx: children,
|
|
38
|
-
hasJsx,
|
|
39
|
-
className,
|
|
40
|
-
disabled: !!disabled,
|
|
41
|
-
group: manualGroup || contextGroup || null
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
registerOption(option)
|
|
45
|
-
return () => unregisterOption(stableId)
|
|
46
|
-
|
|
47
|
-
}, [stableId, value, children, className, disabled, manualGroup, contextGroup, registerOption, unregisterOption])
|
|
48
|
-
|
|
49
|
-
return null
|
|
50
|
-
}
|
package/src/options.jsx
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import {CSSTransition} from 'react-transition-group'
|
|
2
|
-
import {useRef, useState, useEffect, useCallback, memo} from 'react'
|
|
3
|
-
import {createPortal} from 'react-dom'
|
|
4
|
-
|
|
5
|
-
function Options({
|
|
6
|
-
visibility,
|
|
7
|
-
children,
|
|
8
|
-
selectRef,
|
|
9
|
-
onAnimationDone,
|
|
10
|
-
unmount = true,
|
|
11
|
-
duration,
|
|
12
|
-
easing,
|
|
13
|
-
offset,
|
|
14
|
-
animateOpacity,
|
|
15
|
-
style,
|
|
16
|
-
className
|
|
17
|
-
}) {
|
|
18
|
-
|
|
19
|
-
const nodeRef = useRef(null)
|
|
20
|
-
const [selectHeight, setSelectHeight] = useState(0)
|
|
21
|
-
|
|
22
|
-
const [coords, setCoords] = useState({top: 0, left: 0, width: 0})
|
|
23
|
-
|
|
24
|
-
const updateCoords = useCallback(() => {
|
|
25
|
-
if (selectRef?.current) {
|
|
26
|
-
const rect = selectRef.current.getBoundingClientRect()
|
|
27
|
-
const windowHeight = window.innerHeight
|
|
28
|
-
|
|
29
|
-
const dropdownHeight = nodeRef.current?.scrollHeight || 250
|
|
30
|
-
|
|
31
|
-
const spaceBelow = windowHeight - rect.bottom
|
|
32
|
-
const showUpward = spaceBelow < dropdownHeight && rect.top > spaceBelow
|
|
33
|
-
|
|
34
|
-
setCoords({
|
|
35
|
-
top: rect.top,
|
|
36
|
-
bottom: rect.bottom,
|
|
37
|
-
left: rect.left,
|
|
38
|
-
width: rect.width,
|
|
39
|
-
isUpward: showUpward
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
}, [selectRef])
|
|
43
|
-
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
if (visibility) {
|
|
46
|
-
updateCoords()
|
|
47
|
-
|
|
48
|
-
window.addEventListener('scroll', updateCoords, true)
|
|
49
|
-
window.addEventListener('resize', updateCoords)
|
|
50
|
-
|
|
51
|
-
return () => {
|
|
52
|
-
window.removeEventListener('scroll', updateCoords, true)
|
|
53
|
-
window.removeEventListener('resize', updateCoords)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}, [visibility, updateCoords])
|
|
57
|
-
|
|
58
|
-
const transitionString = `height var(--rac-duration) ${easing}${animateOpacity ? `, opacity var(--rac-duration) ${easing}` : ''}`;
|
|
59
|
-
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
if (!selectRef?.current) return
|
|
62
|
-
const updateHeight = () => setSelectHeight(selectRef.current.offsetHeight)
|
|
63
|
-
updateHeight()
|
|
64
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
65
|
-
for (let entry of entries) setSelectHeight(entry.target.offsetHeight)
|
|
66
|
-
})
|
|
67
|
-
resizeObserver.observe(selectRef.current)
|
|
68
|
-
return () => resizeObserver.disconnect()
|
|
69
|
-
}, [selectRef])
|
|
70
|
-
|
|
71
|
-
const baseStyles = {
|
|
72
|
-
position: 'fixed',
|
|
73
|
-
'--rac-duration': `${duration}ms`,
|
|
74
|
-
'--rac-easing': easing,
|
|
75
|
-
left: `${coords.left}px`,
|
|
76
|
-
width: `${coords.width}px`,
|
|
77
|
-
overflow: 'hidden',
|
|
78
|
-
zIndex: '1',
|
|
79
|
-
height: visibility ? 'auto' : '0px',
|
|
80
|
-
opacity: animateOpacity ? (visibility ? 1 : 0) : 1,
|
|
81
|
-
pointerEvents: visibility ? 'all' : 'none',
|
|
82
|
-
visibility: selectHeight ? 'visible' : 'hidden',
|
|
83
|
-
boxSizing: 'border-box',
|
|
84
|
-
transformOrigin: coords.isUpward ? 'bottom' : 'top',
|
|
85
|
-
|
|
86
|
-
...(coords.isUpward ? {
|
|
87
|
-
bottom: `${window.innerHeight - coords.top + offset}px`,
|
|
88
|
-
top: 'auto'
|
|
89
|
-
} : {
|
|
90
|
-
top: `${coords.bottom + offset}px`,
|
|
91
|
-
bottom: 'auto'
|
|
92
|
-
}),
|
|
93
|
-
...Object.fromEntries(
|
|
94
|
-
Object.entries(style || {}).map(([key, value]) => [
|
|
95
|
-
key.startsWith('--') ? key : `--rac-${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`,
|
|
96
|
-
value
|
|
97
|
-
])
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const handleEnter = useCallback(() => {
|
|
102
|
-
const el = nodeRef.current
|
|
103
|
-
if (!el) return
|
|
104
|
-
|
|
105
|
-
el.style.height = '0px'
|
|
106
|
-
if (animateOpacity) el.style.opacity = '0'
|
|
107
|
-
el.style.transition = ''
|
|
108
|
-
}, [animateOpacity])
|
|
109
|
-
|
|
110
|
-
const handleEntering = useCallback(() => {
|
|
111
|
-
const el = nodeRef.current
|
|
112
|
-
if (!el) return
|
|
113
|
-
|
|
114
|
-
el.style.transition = transitionString
|
|
115
|
-
el.style.height = `${el.scrollHeight}px`
|
|
116
|
-
if (animateOpacity) el.style.opacity = '1'
|
|
117
|
-
}, [transitionString, animateOpacity])
|
|
118
|
-
|
|
119
|
-
const handleEntered = useCallback(() => {
|
|
120
|
-
const el = nodeRef.current
|
|
121
|
-
if (!el) return
|
|
122
|
-
|
|
123
|
-
el.style.height = 'auto'
|
|
124
|
-
el.style.transition = ''
|
|
125
|
-
if (onAnimationDone) onAnimationDone()
|
|
126
|
-
}, [onAnimationDone])
|
|
127
|
-
|
|
128
|
-
const handleExit = useCallback(() => {
|
|
129
|
-
const el = nodeRef.current
|
|
130
|
-
if (!el) return
|
|
131
|
-
|
|
132
|
-
el.style.height = `${el.scrollHeight}px`
|
|
133
|
-
if (animateOpacity) el.style.opacity = '1'
|
|
134
|
-
|
|
135
|
-
el.offsetHeight
|
|
136
|
-
el.style.transition = transitionString
|
|
137
|
-
}, [transitionString, animateOpacity])
|
|
138
|
-
|
|
139
|
-
const handleExiting = useCallback(() => {
|
|
140
|
-
const el = nodeRef.current
|
|
141
|
-
if (!el) return
|
|
142
|
-
|
|
143
|
-
el.style.height = '0px'
|
|
144
|
-
if (animateOpacity) el.style.opacity = '0'
|
|
145
|
-
}, [animateOpacity])
|
|
146
|
-
|
|
147
|
-
const handleExited = useCallback(() => {
|
|
148
|
-
const el = nodeRef.current
|
|
149
|
-
if (!el) return
|
|
150
|
-
el.style.transition = ''
|
|
151
|
-
}, [])
|
|
152
|
-
|
|
153
|
-
return createPortal(
|
|
154
|
-
<CSSTransition
|
|
155
|
-
in={visibility}
|
|
156
|
-
timeout={duration}
|
|
157
|
-
classNames='rac-options'
|
|
158
|
-
unmountOnExit={unmount}
|
|
159
|
-
nodeRef={nodeRef}
|
|
160
|
-
onEnter={handleEnter}
|
|
161
|
-
onEntering={handleEntering}
|
|
162
|
-
onEntered={handleEntered}
|
|
163
|
-
onExit={handleExit}
|
|
164
|
-
onExiting={handleExiting}
|
|
165
|
-
onExited={handleExited}
|
|
166
|
-
>
|
|
167
|
-
<div
|
|
168
|
-
ref={nodeRef}
|
|
169
|
-
className={`rac-options ${className || ''}`}
|
|
170
|
-
style={{
|
|
171
|
-
...baseStyles,
|
|
172
|
-
'--rac-duration': `${duration}ms`,
|
|
173
|
-
'--rac-duration-fast': 'calc(var(--rac-duration) * 0.5)',
|
|
174
|
-
'--rac-duration-base': 'var(--rac-duration)',
|
|
175
|
-
'--rac-duration-slow': 'calc(var(--rac-duration) * 1.3)',
|
|
176
|
-
|
|
177
|
-
}}
|
|
178
|
-
onMouseDown={(e) => {
|
|
179
|
-
e.preventDefault()
|
|
180
|
-
}}
|
|
181
|
-
>
|
|
182
|
-
{children}
|
|
183
|
-
</div>
|
|
184
|
-
</CSSTransition>, document.body
|
|
185
|
-
)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export default memo(Options, (prev, next) => {
|
|
189
|
-
return prev.visibility === next.visibility &&
|
|
190
|
-
prev.duration === next.duration &&
|
|
191
|
-
prev.easing === next.easing &&
|
|
192
|
-
prev.offset === next.offset &&
|
|
193
|
-
prev.animateOpacity === next.animateOpacity &&
|
|
194
|
-
prev.selectRef === next.selectRef &&
|
|
195
|
-
prev.children === next.children &&
|
|
196
|
-
JSON.stringify(prev.style) === JSON.stringify(next.style)
|
|
197
|
-
})
|