• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zafle / select_menu / 13996261820

21 Mar 2025 04:22PM UTC coverage: 94.76% (-0.9%) from 95.652%
13996261820

push

github

zafle
fix script bug to run vitest test and coverage (add --config)

117 of 144 branches covered (81.25%)

Branch coverage included in aggregate %.

950 of 982 relevant lines covered (96.74%)

42.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.83
/lib/components/SelectInput/SelectInput.jsx
1
import useConfig from '../../context/hook/useConfig'
1✔
2
import useSelect from '../../context/hook/useSelect'
1✔
3
import arrow from '../../assets/caret-down-icon.png'
1✔
4
import closeIcon from '../../assets/close-line-icon.png'
1✔
5
import { triggerOnChangeSelectedValueInput } from '../../utils/utils'
1✔
6
import { useEffect } from 'react'
1✔
7
import PropTypes from 'prop-types'
1✔
8
import styles from './SelectInput.module.css'
1✔
9

10
/**
11
 * Displays Select input
12
 *
13
 * @returns {React.ReactElement} SelectInput
14
 */
15
export default function SelectInput({ selectedOption }) {
37✔
16
  //  get context
17
  const {
37✔
18
    selectedId,
37✔
19
    selectedText,
37✔
20
    selectedValue,
37✔
21
    defaultSelected,
37✔
22
    isOpen,
37✔
23
    toggleIsOpen,
37✔
24
    clearSelected,
37✔
25
    defineSelected,
37✔
26
  } = useSelect()
37✔
27

28
  const {
37✔
29
    id,
37✔
30
    labelId,
37✔
31
    name,
37✔
32
    onChangeValue,
37✔
33
    resetToDefault,
37✔
34
    values,
37✔
35
    colorOnFocus,
37✔
36
    classOnFocus,
37✔
37
    border,
37✔
38
    inputHeight,
37✔
39
    inputBackground,
37✔
40
    inputTextColor,
37✔
41
    inputBorderRadiusOpened,
37✔
42
    borderRadius,
37✔
43
    inputVerticalPadding,
37✔
44
    inputHorizontalPadding,
37✔
45
    inputFontSize,
37✔
46
    boxShadow,
37✔
47
    boxShadowOnOpen,
37✔
48
    dropdownPosition,
37✔
49
  } = useConfig()
37✔
50

51
  const toggleDropdown = (e) => {
37✔
52
    // if event is not from clear selection element
53
    if (e.target.dataset.name !== 'clear') {
12✔
54
      toggleIsOpen()
10✔
55
    }
10✔
56
  }
12✔
57
  const clearSelection = () => {
37✔
58
    triggerOnChangeSelectedValueInput('', id)
2✔
59
    clearSelected()
2✔
60
  }
2✔
61

62
  // Handle hidden input on change event
63
  const handleChange = (e) => {
37✔
64
    // custom onChangeValue function from config
65
    onChangeValue !== null ? onChangeValue(e.target.value) : e.preventDefault()
5!
66
  }
5✔
67

68
  // Handle visible input controls
69
  const handleInputClick = (e) => {
37✔
70
    toggleDropdown(e)
5✔
71
  }
5✔
72
  const handleInputKeyDown = (e) => {
37✔
73
    if (e.key === ' ' || e.key === 'Spacebar' || e.key === 'Enter') {
8✔
74
      e.preventDefault()
7✔
75
      toggleDropdown(e)
7✔
76
    }
7✔
77
  }
8✔
78

79
  // Handle clear input controls
80
  const handleClearClick = () => {
37✔
81
    clearSelection()
1✔
82
  }
1✔
83
  const handleClearKeyDown = (e) => {
37✔
84
    if (e.key === ' ' || e.key === 'Spacebar' || e.key === 'Enter') {
1✔
85
      e.preventDefault()
1✔
86
      clearSelection()
1✔
87
    }
1✔
88
  }
1✔
89

90
  /**
91
   * This function is added in V2
92
   *
93
   * Check equality with selectedOption state (new prop) and selectedText | selectedValue
94
   * If different, means that user injected new value programmatically (null | '' | any)
95
   * This will reset selection to '' | defaultSelected if resetToDefault is true
96
   */
97
  useEffect(() => {
37✔
98
    if (selectedOption !== undefined) {
18!
99
      const selectedContent = values ? selectedValue : selectedText
×
100

101
      if (selectedOption !== selectedContent) {
×
102
        if (!resetToDefault) {
×
103
          triggerOnChangeSelectedValueInput('', id)
×
104
          clearSelected()
×
105
        } else if (resetToDefault) {
×
106
          defineSelected(
×
107
            defaultSelected.id,
×
108
            defaultSelected.text,
×
109
            defaultSelected.value,
×
110
            defaultSelected.index
×
111
          )
×
112
          onChangeValue(defaultSelected.value)
×
113
        }
×
114
      }
×
115
    }
×
116
    // NOTE: Run effect only when selectedOption changes,
117
    // please recheck dependencies if effect is updated.
118
    // eslint-disable-next-line react-hooks/exhaustive-deps
119
  }, [selectedOption])
37✔
120

121
  const selectInputStyle = {
37✔
122
    border: border,
37✔
123
    height: inputHeight,
37✔
124
    background: inputBackground,
37✔
125
    color: inputTextColor,
37✔
126
    borderRadius: isOpen ? inputBorderRadiusOpened : borderRadius,
37✔
127
    padding: `${inputVerticalPadding} ${inputHorizontalPadding}`,
37✔
128
    fontSize: inputFontSize,
37✔
129
    boxShadow: boxShadowOnOpen ? (isOpen ? boxShadow : 'unset') : boxShadow,
37!
130
    zIndex: dropdownPosition === 'top' && isOpen ? '2' : 'auto',
37!
131
  }
37✔
132

133
  return (
37✔
134
    <div
37✔
135
      className={
37✔
136
        `select-input ${styles.selectInput} ` +
37✔
137
        (colorOnFocus !== 'default' ? `${styles[classOnFocus]} ` : '') +
37!
138
        (selectedText !== '' ? `select-input--has-selection ` : '')
37✔
139
      }
140
      style={selectInputStyle}
37✔
141
      tabIndex="0"
37✔
142
      role="combobox"
37✔
143
      aria-expanded={isOpen}
37✔
144
      aria-haspopup="listbox"
37✔
145
      aria-controls={`dropdown_${id}`}
37✔
146
      aria-activedescendant={selectedId}
37✔
147
      aria-labelledby={labelId}
37✔
148
      onClick={(e) => {
37✔
149
        handleInputClick(e)
5✔
150
      }}
5✔
151
      onKeyDown={(e) => {
37✔
152
        handleInputKeyDown(e)
8✔
153
      }}
8✔
154
      data-testid="select-input"
37✔
155
    >
156
      {/* Hidden in css input */}
157
      <input
37✔
158
        id={id}
37✔
159
        className={`select-input--value ${styles.selectedValue}`}
37✔
160
        type="text"
37✔
161
        onChange={(e) => {
37✔
162
          handleChange(e)
5✔
163
        }}
5✔
164
        name={name}
37✔
165
        value={selectedValue}
37✔
166
        aria-hidden="true"
37✔
167
        tabIndex="-1"
37✔
168
        readOnly
37✔
169
        data-testid="selectedValue-input"
37✔
170
      />
37✔
171
      <div
37✔
172
        className={`select-input--text ${styles.selectedText}`}
37✔
173
        data-testid="selectedText-input"
37✔
174
      >
175
        {selectedText}
37✔
176
      </div>
37✔
177
      <img
37✔
178
        className={
37✔
179
          `select-input--clear-icon ${styles.clearSelect} ${styles.selectControl} ` +
37✔
180
          (selectedText !== '' ? `${styles.hasSelection} ` : '') +
37✔
181
          (colorOnFocus !== 'default' ? `${styles[classOnFocus]} ` : '')
37!
182
        }
183
        src={closeIcon}
37✔
184
        alt="clear selection"
37✔
185
        data-name="clear"
37✔
186
        tabIndex="0"
37✔
187
        aria-label="clear selection"
37✔
188
        role="button"
37✔
189
        onClick={() => {
37✔
190
          handleClearClick()
1✔
191
        }}
1✔
192
        onKeyDown={(e) => {
37✔
193
          handleClearKeyDown(e)
1✔
194
        }}
1✔
195
        data-testid="clearSelected-button"
37✔
196
      />
37✔
197
      <img
37✔
198
        className={
37✔
199
          `select-input--arrow ${styles.selectArrow} ${styles.selectControl} ` +
37✔
200
          (isOpen && `select-input--arrow-isopen `) +
37✔
201
          (isOpen && styles.open)
37✔
202
        }
203
        src={arrow}
37✔
204
        alt="select menu control"
37✔
205
      />
37✔
206
    </div>
37✔
207
  )
208
}
37✔
209

210
SelectInput.propTypes = {
1✔
211
  selectedOption: PropTypes.string,
1✔
212
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc