react-animated-select 0.2.9 → 0.3.6
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 +53 -29
- package/demo/README.md +16 -0
- package/demo/eslint.config.js +29 -0
- package/demo/index.html +13 -0
- package/demo/package-lock.json +3436 -0
- package/demo/package.json +38 -0
- package/demo/public/vite.svg +1 -0
- package/demo/src/App.tsx +425 -0
- package/demo/src/main.jsx +9 -0
- package/demo/src/rac.css +735 -0
- package/demo/src/shake.js +11 -0
- package/demo/src/slideDown.jsx +35 -0
- package/demo/vite.config.js +7 -0
- package/dist/index.cjs.js +6 -9
- package/dist/index.css +1 -1
- package/dist/index.es.js +926 -687
- package/index.d.ts +20 -2
- package/package.json +3 -2
- package/src/index.js +1 -0
- package/src/optgroup.jsx +36 -0
- package/src/option.jsx +31 -11
- package/src/options.jsx +11 -11
- package/src/select.css +45 -1
- package/src/select.jsx +209 -238
- package/src/selectContext.js +1 -1
- package/src/selectJSX.jsx +148 -0
- package/src/slideDown.jsx +36 -0
- package/src/useSelect.jsx +113 -79
- package/src/useSelectLogic.jsx +215 -131
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {FC, ReactNode} from 'react'
|
|
1
|
+
import {FC, ReactNode, CSSProperties, ElementType} from 'react'
|
|
2
2
|
|
|
3
3
|
export interface SelectProps {
|
|
4
4
|
|
|
@@ -38,6 +38,15 @@ export interface SelectProps {
|
|
|
38
38
|
style?: CSSProperties
|
|
39
39
|
ArrowIcon?: ElementType | string | ReactNode
|
|
40
40
|
ClearIcon?: ElementType | string | ReactNode
|
|
41
|
+
|
|
42
|
+
hasMore?: boolean
|
|
43
|
+
loadMore?: () => void
|
|
44
|
+
loadButton?: boolean
|
|
45
|
+
loadButtonText?: string
|
|
46
|
+
loadMoreText?: string
|
|
47
|
+
loadOffset?: number
|
|
48
|
+
loadAhead?: number
|
|
49
|
+
childrenFirst?: boolean
|
|
41
50
|
}
|
|
42
51
|
|
|
43
52
|
export const Select: FC<SelectProps>
|
|
@@ -50,4 +59,13 @@ export interface OptionProps {
|
|
|
50
59
|
className?: string
|
|
51
60
|
}
|
|
52
61
|
|
|
53
|
-
export const Option: FC<OptionProps>
|
|
62
|
+
export const Option: FC<OptionProps>
|
|
63
|
+
|
|
64
|
+
export interface OptGroupProps {
|
|
65
|
+
value?: any
|
|
66
|
+
id?: any
|
|
67
|
+
name?: any
|
|
68
|
+
label?: any
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const OptGroup: FC<OptGroup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-animated-select",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "l1nway (https://github.com/l1nway/)",
|
|
6
6
|
"description": "Animated, accessible, and flexible select component for React",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"url": "git+https://github.com/l1nway/react-animated-select.git"
|
|
17
17
|
},
|
|
18
18
|
"license": "MIT",
|
|
19
|
-
"homepage": "https://github.
|
|
19
|
+
"homepage": "https://l1nway.github.io/react-animated-select/",
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "vite build",
|
|
22
22
|
"dev": "vite build --watch"
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"react-transition-group": "^4.4.5"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
+
"@types/react": "^19.2.9",
|
|
43
44
|
"@vitejs/plugin-react": "^5.1.2",
|
|
44
45
|
"vite": "^7.3.1",
|
|
45
46
|
"vite-plugin-lib-inject-css": "^2.2.2"
|
package/src/index.js
CHANGED
package/src/optgroup.jsx
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
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
CHANGED
|
@@ -1,28 +1,48 @@
|
|
|
1
|
-
import {useEffect, useContext} from 'react'
|
|
1
|
+
import {useEffect, useContext, useMemo, useId} from 'react'
|
|
2
2
|
import {SelectContext} from './selectContext'
|
|
3
|
-
import {
|
|
3
|
+
import {GroupContext} from './optgroup'
|
|
4
4
|
import getText from './getText'
|
|
5
5
|
|
|
6
|
-
export default function Option({value, id, className, children, disabled}) {
|
|
6
|
+
export default function Option({value, id, className, children, disabled, group: manualGroup}) {
|
|
7
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])
|
|
8
17
|
|
|
9
18
|
useEffect(() => {
|
|
10
|
-
if (!
|
|
19
|
+
if (!registerOption) return
|
|
11
20
|
|
|
12
21
|
const textFallback = getText(children)
|
|
13
|
-
|
|
22
|
+
let finalLabel = ''
|
|
23
|
+
|
|
24
|
+
if (typeof children === 'string' && children !== '') {
|
|
25
|
+
finalLabel = children
|
|
26
|
+
} else if (textFallback) {
|
|
27
|
+
finalLabel = textFallback
|
|
28
|
+
} else if (value !== undefined && value !== null) {
|
|
29
|
+
finalLabel = String(value)
|
|
30
|
+
}
|
|
31
|
+
|
|
14
32
|
const option = {
|
|
15
|
-
id:
|
|
33
|
+
id: stableId,
|
|
16
34
|
value: value !== undefined ? value : textFallback,
|
|
17
|
-
label:
|
|
35
|
+
label: finalLabel,
|
|
18
36
|
jsx: children,
|
|
19
37
|
className,
|
|
20
|
-
disabled: !!disabled
|
|
38
|
+
disabled: !!disabled,
|
|
39
|
+
group: manualGroup || contextGroup || null
|
|
21
40
|
}
|
|
22
41
|
|
|
23
|
-
|
|
24
|
-
return () =>
|
|
25
|
-
|
|
42
|
+
registerOption(option)
|
|
43
|
+
return () => unregisterOption(stableId)
|
|
44
|
+
|
|
45
|
+
}, [stableId, value, children, className, disabled, manualGroup, contextGroup, registerOption, unregisterOption])
|
|
26
46
|
|
|
27
47
|
return null
|
|
28
48
|
}
|
package/src/options.jsx
CHANGED
|
@@ -30,17 +30,17 @@ function Options({
|
|
|
30
30
|
const transitionString = `height ${duration}ms ${easing}${animateOpacity ? `, opacity ${duration}ms ${easing}` : ''}`
|
|
31
31
|
|
|
32
32
|
const baseStyles = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
position: 'absolute',
|
|
34
|
+
top: `calc(100% + ${offset}px)`,
|
|
35
|
+
left: '0',
|
|
36
|
+
width: '100%',
|
|
37
|
+
overflow: 'hidden',
|
|
38
|
+
marginTop: '2px',
|
|
39
|
+
zIndex: '1',
|
|
40
|
+
height: visibility ? 'auto' : '0px',
|
|
41
|
+
opacity: animateOpacity ? (visibility ? 1 : 0) : 1,
|
|
42
|
+
pointerEvents: visibility ? 'all' : 'none',
|
|
43
|
+
visibility: selectHeight ? 'visible' : 'hidden'
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const handleEnter = useCallback(() => {
|
package/src/select.css
CHANGED
|
@@ -56,12 +56,21 @@
|
|
|
56
56
|
--rac-list-max-height: 250px;
|
|
57
57
|
|
|
58
58
|
--rac-option-padding: 0.5em;
|
|
59
|
+
--rac-option-min-height: 1em;
|
|
59
60
|
--rac-disabled-option-color: color-mix(in srgb, GrayText, CanvasText 20%);
|
|
60
61
|
--rac-invalid-option-color: color-mix(in srgb, var(--rac-base-red), CanvasText 10%);
|
|
61
62
|
--rac-true-option-color: color-mix(in srgb, var(--rac-base-green), CanvasText 10%);
|
|
62
63
|
--rac-false-option-color: color-mix(in srgb, var(--rac-base-red), CanvasText 10%);
|
|
63
64
|
--rac-warning-option-color: color-mix(in srgb, var(--rac-base-yellow), CanvasText 10%);
|
|
64
65
|
|
|
66
|
+
--rac-group-header-font-size: 1.25em;
|
|
67
|
+
--rac-group-header-font-weight: bold;
|
|
68
|
+
--rac-group-header-min-height: 1em;
|
|
69
|
+
--rac-group-header-padding: 0.5em;
|
|
70
|
+
--rac-group-arrow-height: 1em;
|
|
71
|
+
--rac-group-arrow-width: 1em;
|
|
72
|
+
--rac-group-arrow-padding: 1px 0 2px;
|
|
73
|
+
|
|
65
74
|
background: var(--rac-select-background);
|
|
66
75
|
padding: var(--rac-select-padding);
|
|
67
76
|
border: var(--rac-select-border);
|
|
@@ -197,11 +206,12 @@
|
|
|
197
206
|
}
|
|
198
207
|
|
|
199
208
|
.rac-select-option {
|
|
209
|
+
min-height: var(--rac-option-min-height);
|
|
200
210
|
padding: var(--rac-option-padding);
|
|
201
211
|
transition: background-color var(--rac-duration-fast) cubic-bezier(0.4,0,0.2,1);
|
|
202
212
|
}
|
|
203
213
|
|
|
204
|
-
.rac-select-option:not(.rac-disabled-option):hover {
|
|
214
|
+
.rac-select-option:not(.rac-disabled-option):not(.rac-group-option):hover {
|
|
205
215
|
background-color: var(--rac-option-hover);
|
|
206
216
|
}
|
|
207
217
|
|
|
@@ -232,4 +242,38 @@
|
|
|
232
242
|
|
|
233
243
|
.rac-false-option {
|
|
234
244
|
color: var(--rac-false-option-color);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.rac-loading-option {
|
|
248
|
+
cursor: wait;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.rac-group-header {
|
|
252
|
+
cursor: pointer;
|
|
253
|
+
min-height: var(--rac-group-header-min-height);
|
|
254
|
+
padding: var(--rac-group-header-padding);
|
|
255
|
+
transition: background-color var(--rac-duration-fast) cubic-bezier(0.4,0,0.2,1);
|
|
256
|
+
display: flex;
|
|
257
|
+
justify-content: space-between;
|
|
258
|
+
align-items: center;
|
|
259
|
+
font-weight: var(--rac-group-header-font-weight);
|
|
260
|
+
font-size: var(--rac-group-header-font-size);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.rac-group-arrow-wrapper {
|
|
264
|
+
display: block;
|
|
265
|
+
height: var(--rac-group-arrow-height);
|
|
266
|
+
width: var(--rac-group-arrow-width);
|
|
267
|
+
padding: var(--rac-group-arrow-padding);
|
|
268
|
+
|
|
269
|
+
will-change: transform;
|
|
270
|
+
transition:
|
|
271
|
+
transform var(--rac-duration-base) cubic-bezier(.4,0,.2,1),
|
|
272
|
+
padding var(--rac-duration-fast);
|
|
273
|
+
transform-origin: 50% 50%;
|
|
274
|
+
transform: translateZ(0);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.rac-group-arrow-wrapper.--open {
|
|
278
|
+
transform: rotate(180deg);
|
|
235
279
|
}
|