react-animated-select 0.2.5 → 0.2.7
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 +39 -25
- package/dist/index.cjs.js +9 -8
- package/dist/index.css +1 -1
- package/dist/index.es.js +452 -426
- package/index.d.ts +7 -4
- package/package.json +1 -1
- package/src/icons.jsx +18 -16
- package/src/select.css +24 -1
- package/src/select.jsx +61 -16
- package/src/slideLeft.jsx +4 -3
package/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export interface SelectProps {
|
|
|
18
18
|
options?: any[] | Record<string, any>
|
|
19
19
|
value?: any
|
|
20
20
|
defaultValue?: any
|
|
21
|
-
onChange?: (
|
|
21
|
+
onChange?: (data: any, id: any) => void
|
|
22
22
|
|
|
23
23
|
disabled?: boolean
|
|
24
24
|
loading?: boolean
|
|
@@ -35,14 +35,17 @@ export interface SelectProps {
|
|
|
35
35
|
invalidOption?: string
|
|
36
36
|
|
|
37
37
|
className?: string
|
|
38
|
-
|
|
38
|
+
style?: CSSProperties
|
|
39
|
+
ArrowIcon?: ElementType | string | ReactNode
|
|
40
|
+
ClearIcon?: ElementType | string | ReactNode
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export const Select: FC<SelectProps>
|
|
42
44
|
|
|
43
45
|
export interface OptionProps {
|
|
44
|
-
value
|
|
45
|
-
|
|
46
|
+
value?: any
|
|
47
|
+
id?: any
|
|
48
|
+
children?: ReactNode
|
|
46
49
|
disabled?: boolean
|
|
47
50
|
className?: string
|
|
48
51
|
}
|
package/package.json
CHANGED
package/src/icons.jsx
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
export const XMarkIcon = ({className = '', ...props}) => (
|
|
2
2
|
<svg
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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}
|
|
10
12
|
>
|
|
11
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"/>
|
|
12
14
|
</svg>
|
|
13
15
|
)
|
|
14
16
|
|
|
15
|
-
export const ArrowUpIcon = ({
|
|
17
|
+
export const ArrowUpIcon = ({className = '', ...props}) => (
|
|
16
18
|
<svg
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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}
|
|
24
26
|
>
|
|
25
|
-
|
|
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"/>
|
|
26
28
|
</svg>
|
|
27
29
|
)
|
package/src/select.css
CHANGED
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
--rac-select-padding: 0em 0.5em;
|
|
22
22
|
--rac-disabled-opacity: 0.75;
|
|
23
23
|
|
|
24
|
+
--rac-title-anim-shift: 4px;
|
|
25
|
+
--rac-title-anim-entry-ease: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
26
|
+
|
|
24
27
|
--rac-dots-height: 3px;
|
|
25
28
|
--rac-dots-width: 3px;
|
|
26
29
|
--rac-dots-color: currentColor;
|
|
@@ -97,11 +100,26 @@
|
|
|
97
100
|
align-items: center;
|
|
98
101
|
}
|
|
99
102
|
|
|
103
|
+
.rac-title-text {
|
|
104
|
+
display: block;
|
|
105
|
+
animation: rac-fade-in var(--rac-duration-base) var(--rac-title-anim-entry-ease);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@keyframes rac-fade-in {
|
|
109
|
+
from {
|
|
110
|
+
opacity: 0;
|
|
111
|
+
transform: translateY(var(--rac-title-anim-shift));
|
|
112
|
+
}
|
|
113
|
+
to {
|
|
114
|
+
opacity: 1;
|
|
115
|
+
transform: translateY(0);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
100
119
|
.rac-loading-dots {
|
|
101
120
|
display: inline-flex;
|
|
102
121
|
gap: var(--rac-dots-gap);
|
|
103
122
|
padding-left: var(--rac-dots-padding-left);
|
|
104
|
-
height: 90%;
|
|
105
123
|
align-items: var(--rac-dots-align);
|
|
106
124
|
}
|
|
107
125
|
|
|
@@ -155,6 +173,11 @@
|
|
|
155
173
|
transform: rotate(180deg);
|
|
156
174
|
}
|
|
157
175
|
|
|
176
|
+
.rac-select-arrow,
|
|
177
|
+
.rac-select-cancel {
|
|
178
|
+
object-fit: contain;
|
|
179
|
+
}
|
|
180
|
+
|
|
158
181
|
.rac-select-list {
|
|
159
182
|
background-color: var(--rac-list-background);
|
|
160
183
|
color: var(--rac-list-color);
|
package/src/select.jsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import './select.css'
|
|
2
2
|
|
|
3
3
|
import {XMarkIcon, ArrowUpIcon} from './icons'
|
|
4
|
-
import {useRef, useMemo, useState, useEffect, useCallback, useId} from 'react'
|
|
4
|
+
import {forwardRef, useImperativeHandle, useRef, useMemo, useState, useEffect, useCallback, useId, isValidElement, cloneElement} from 'react'
|
|
5
5
|
|
|
6
6
|
import {SelectContext} from './selectContext'
|
|
7
7
|
import useSelect from './useSelect'
|
|
@@ -10,7 +10,26 @@ import {makeId} from './makeId'
|
|
|
10
10
|
import Options from './options'
|
|
11
11
|
import SlideLeft from './slideLeft'
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
const renderIcon = (Icon, defaultProps) => {
|
|
14
|
+
if (!Icon) return null
|
|
15
|
+
|
|
16
|
+
if (typeof Icon === 'string') {
|
|
17
|
+
return <img src={Icon} {...defaultProps} alt='' />
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (isValidElement(Icon)) {
|
|
21
|
+
return cloneElement(Icon, defaultProps)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (typeof Icon === 'function' || (typeof Icon === 'object' && Icon.$$typeof)) {
|
|
25
|
+
const IconComponent = Icon
|
|
26
|
+
return <IconComponent {...defaultProps} />
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const Select = forwardRef(({
|
|
14
33
|
unmount,
|
|
15
34
|
children,
|
|
16
35
|
renderedDropdown,
|
|
@@ -21,8 +40,12 @@ export default function Select({
|
|
|
21
40
|
easing = 'ease-out',
|
|
22
41
|
offset = 2,
|
|
23
42
|
animateOpacity = true,
|
|
43
|
+
style = {},
|
|
44
|
+
className = '',
|
|
45
|
+
ArrowIcon = ArrowUpIcon,
|
|
46
|
+
ClearIcon = XMarkIcon,
|
|
24
47
|
...props
|
|
25
|
-
}) {
|
|
48
|
+
}, ref) => {
|
|
26
49
|
|
|
27
50
|
const reactId = useId()
|
|
28
51
|
|
|
@@ -41,6 +64,17 @@ export default function Select({
|
|
|
41
64
|
// ref is needed to pass dimensions for the animation hook
|
|
42
65
|
const selectRef = useRef(null)
|
|
43
66
|
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (!ref) return
|
|
69
|
+
if (typeof ref === 'function') {
|
|
70
|
+
ref(selectRef.current)
|
|
71
|
+
} else {
|
|
72
|
+
ref.current = selectRef.current
|
|
73
|
+
}
|
|
74
|
+
}, [ref])
|
|
75
|
+
|
|
76
|
+
useImperativeHandle(ref, () => selectRef.current)
|
|
77
|
+
|
|
44
78
|
// open/closed status select
|
|
45
79
|
const [internalVisibility, setInternalVisibility] = useState(false)
|
|
46
80
|
|
|
@@ -203,8 +237,12 @@ export default function Select({
|
|
|
203
237
|
{children}
|
|
204
238
|
{renderedDropdown}
|
|
205
239
|
<div
|
|
206
|
-
style={{
|
|
240
|
+
style={{
|
|
241
|
+
'--rac-duration': `${duration}ms`,
|
|
242
|
+
...style
|
|
243
|
+
}}
|
|
207
244
|
className={`rac-select
|
|
245
|
+
${className}
|
|
208
246
|
${(!hasOptions || disabled) ? 'rac-disabled-style' : ''}
|
|
209
247
|
${loading ? 'rac-loading-style' : ''}
|
|
210
248
|
${error ? 'rac-error-style' : ''}`
|
|
@@ -225,12 +263,17 @@ export default function Select({
|
|
|
225
263
|
})}
|
|
226
264
|
>
|
|
227
265
|
<div
|
|
228
|
-
className={`rac-select-title ${selected?.type == 'boolean'
|
|
266
|
+
className={`rac-select-title ${(!error && !loading && selected?.type == 'boolean')
|
|
229
267
|
? selected.raw ? 'rac-true-option' : 'rac-false-option'
|
|
230
268
|
: ''
|
|
231
269
|
}`}
|
|
232
270
|
>
|
|
233
|
-
|
|
271
|
+
<span
|
|
272
|
+
className='rac-title-text'
|
|
273
|
+
key={title}
|
|
274
|
+
>
|
|
275
|
+
{title}
|
|
276
|
+
</span>
|
|
234
277
|
<SlideLeft
|
|
235
278
|
visibility={loading && !error}
|
|
236
279
|
duration={duration}
|
|
@@ -246,24 +289,24 @@ export default function Select({
|
|
|
246
289
|
<SlideLeft
|
|
247
290
|
visibility={hasActualValue && hasOptions && !disabled && !loading && !error}
|
|
248
291
|
duration={duration}
|
|
292
|
+
style={{display: 'grid'}}
|
|
249
293
|
>
|
|
250
|
-
|
|
251
|
-
className
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
onClick={(e) => clear(e)}
|
|
255
|
-
/>
|
|
294
|
+
{renderIcon(ClearIcon, {
|
|
295
|
+
className: 'rac-select-cancel',
|
|
296
|
+
onClick: (e) => clear(e)
|
|
297
|
+
})}
|
|
256
298
|
</SlideLeft>
|
|
257
299
|
<SlideLeft
|
|
258
300
|
visibility={active}
|
|
259
301
|
duration={duration}
|
|
302
|
+
style={{display: 'grid'}}
|
|
260
303
|
>
|
|
261
304
|
<span
|
|
262
305
|
className={`rac-select-arrow-wrapper ${visibility ? '--open' : ''}`}
|
|
263
306
|
>
|
|
264
|
-
|
|
265
|
-
className
|
|
266
|
-
|
|
307
|
+
{renderIcon(ArrowIcon, {
|
|
308
|
+
className: 'rac-select-arrow-wrapper'
|
|
309
|
+
})}
|
|
267
310
|
</span>
|
|
268
311
|
</SlideLeft>
|
|
269
312
|
</div>
|
|
@@ -288,4 +331,6 @@ export default function Select({
|
|
|
288
331
|
</div>
|
|
289
332
|
</SelectContext.Provider>
|
|
290
333
|
)
|
|
291
|
-
}
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
export default Select
|
package/src/slideLeft.jsx
CHANGED
|
@@ -4,8 +4,9 @@ import {useRef} from 'react'
|
|
|
4
4
|
function SlideLeft({
|
|
5
5
|
visibility,
|
|
6
6
|
children,
|
|
7
|
-
duration,
|
|
8
|
-
unmount
|
|
7
|
+
duration = 300,
|
|
8
|
+
unmount,
|
|
9
|
+
style
|
|
9
10
|
}) {
|
|
10
11
|
const nodeRef = useRef(null)
|
|
11
12
|
|
|
@@ -26,7 +27,7 @@ function SlideLeft({
|
|
|
26
27
|
<div
|
|
27
28
|
ref={nodeRef}
|
|
28
29
|
style={{
|
|
29
|
-
|
|
30
|
+
...style,
|
|
30
31
|
overflow: 'hidden',
|
|
31
32
|
transition: `width ${duration}ms ease`
|
|
32
33
|
}}
|