react-animated-select 0.1.5 → 0.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-animated-select",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "author": "l1nway (https://github.com/l1nway/)",
6
6
  "description": "Animated, accessible, and flexible select component for React",
@@ -0,0 +1,11 @@
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/option.jsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import {useEffect, useContext} from 'react'
2
2
  import {SelectContext} from './selectContext'
3
3
  import {makeId} from './makeId'
4
+ import getText from './getText'
4
5
 
5
6
  export default function Option({value, id, className, children, disabled}) {
6
7
  const ctx = useContext(SelectContext)
@@ -8,9 +9,11 @@ export default function Option({value, id, className, children, disabled}) {
8
9
  useEffect(() => {
9
10
  if (!ctx) return
10
11
 
12
+ const textFallback = getText(children)
13
+
11
14
  const option = {
12
- id: id ?? makeId(String(value ?? children)),
13
- value,
15
+ id: String(id ?? makeId(String(textFallback))),
16
+ value: value !== undefined ? value : textFallback,
14
17
  label: typeof children === 'string' ? children : String(value ?? id),
15
18
  jsx: children,
16
19
  className,
@@ -22,4 +25,4 @@ export default function Option({value, id, className, children, disabled}) {
22
25
  }, [id, value, children, className, disabled])
23
26
 
24
27
  return null
25
- }
28
+ }
package/src/select.css CHANGED
@@ -125,8 +125,8 @@
125
125
 
126
126
  .rac-select-option {
127
127
  padding: 0.5em;
128
- transition: background-color 300ms, border-radius 300ms, font-size 300ms, 300ms height;
129
- transition: background-color 300ms, border-radius 300ms, font-size 300ms, 300ms height;
128
+ transition: background-color 300ms cubic-bezier(0.4, 0, 0.2, 1), border-radius 300ms, font-size 300ms, 300ms height;
129
+ background-color: transparent;
130
130
  }
131
131
 
132
132
  .rac-select-option:not(.rac-disabled-option):hover {
package/src/select.jsx CHANGED
@@ -63,7 +63,7 @@ export default function Select({children, renderedDropdown, ...props}) {
63
63
 
64
64
  const option = normalizedOptions[highlightedIndex]
65
65
  if (option) {
66
- const elementId = `option-${makeId(option.name)}-${selectId}`
66
+ const elementId = `opt-${selectId}-${makeId(option.id)}`
67
67
  const domElement = document.getElementById(elementId)
68
68
 
69
69
  if (domElement) {
@@ -85,7 +85,7 @@ export default function Select({children, renderedDropdown, ...props}) {
85
85
  if (loading) return loadingText
86
86
  if (disabled) return disabledText
87
87
 
88
- if (selected) return selected.name
88
+ if (selected) return selected.jsx ?? selected.name
89
89
 
90
90
  if (hasActualValue) {
91
91
  return typeof selectedValue === 'object'
@@ -102,11 +102,13 @@ export default function Select({children, renderedDropdown, ...props}) {
102
102
 
103
103
  // option list rendering
104
104
  const renderOptions = useMemo(() => normalizedOptions?.map((element, index) => {
105
- const optionId = `option-${makeId(element.name)}-${selectId}`
105
+ const optionId = `opt-${selectId}-${makeId(element.id)}`
106
106
 
107
107
  let optionClass = 'rac-select-option'
108
108
  if (element.className) optionClass += ` ${element.className}`
109
109
 
110
+ if (selected?.id === element.id) optionClass += ' rac-selected'
111
+
110
112
  if (index === highlightedIndex) optionClass += ' rac-highlighted'
111
113
 
112
114
  if (element.disabled) optionClass += ' rac-disabled-option'
@@ -199,7 +201,7 @@ export default function Select({children, renderedDropdown, ...props}) {
199
201
  visibility={loading && !error}
200
202
  >
201
203
  <span className='rac-loading-dots'>
202
- <i></i><i></i><i></i>
204
+ <i/><i/><i/>
203
205
  </span>
204
206
  </SlideLeft>
205
207
  </div>
package/src/slideLeft.jsx CHANGED
@@ -8,7 +8,7 @@ function SlideLeft({visibility, children, duration = 300, unmount}) {
8
8
  <CSSTransition
9
9
  in={visibility}
10
10
  timeout={duration}
11
- classNames='slide-left'
11
+ classNames='rac-slide-left'
12
12
  unmountOnExit
13
13
  nodeRef={nodeRef}
14
14
  onEnter={() => (nodeRef.current.style.width = '0px')}
package/src/useSelect.jsx CHANGED
@@ -13,14 +13,22 @@ function useSelect({
13
13
 
14
14
  useEffect(() => {
15
15
  if (isOpen) {
16
- const index = selected
17
- ? options.findIndex(o => o.id == selected.id)
18
- : -1
19
- setHighlightedIndex(index >= 0 ? index : 0)
16
+ let index = -1
17
+
18
+ if (selected) {
19
+ const selectedIndex = options.findIndex(o => o.id === selected.id && !o.disabled)
20
+ if (selectedIndex >= 0) index = selectedIndex
21
+ }
22
+
23
+ if (index === -1) {
24
+ index = options.findIndex(o => !o.disabled)
25
+ }
26
+
27
+ setHighlightedIndex(index)
20
28
  } else {
21
29
  setHighlightedIndex(-1)
22
30
  }
23
- }, [isOpen, selected])
31
+ }, [isOpen, selected, options])
24
32
 
25
33
  const handleBlur = useCallback((e) => {
26
34
  if (e.currentTarget.contains(e.relatedTarget)) return
@@ -49,20 +57,22 @@ function useSelect({
49
57
  }, [disabled, isOpen, setIsOpen])
50
58
 
51
59
  const getNextIndex = (current, direction) => {
52
- let next = current + direction
53
- if (next < 0) next = options.length - 1
54
- if (next >= options.length) next = 0
55
-
60
+ if (options.every(o => o.disabled)) return -1
61
+
62
+ let next = current
56
63
  let loops = 0
57
- while (options[next]?.disabled && loops < options.length) {
64
+
65
+ do {
58
66
  next += direction
59
67
  if (next < 0) next = options.length - 1
60
68
  if (next >= options.length) next = 0
61
69
  loops++
62
- }
70
+ } while (options[next]?.disabled && loops <= options.length)
71
+
63
72
  return next
64
73
  }
65
74
 
75
+
66
76
  const handleKeyDown = useCallback((e) => {
67
77
  if (disabled) return
68
78