( props: HiddenSelectProps<T, M> )
| 153 | * form autofill, mobile form navigation, and native form submission. |
| 154 | */ |
| 155 | export function HiddenSelect<T, M extends SelectionMode = 'single'>( |
| 156 | props: HiddenSelectProps<T, M> |
| 157 | ): JSX.Element | null { |
| 158 | let {state, triggerRef, label, name, form, isDisabled} = props; |
| 159 | let selectRef = useRef(null); |
| 160 | let inputRef = useRef(null); |
| 161 | let {containerProps, selectProps} = useHiddenSelect( |
| 162 | {...props, selectRef: state.collection.size <= 300 ? selectRef : inputRef}, |
| 163 | state, |
| 164 | triggerRef |
| 165 | ); |
| 166 | |
| 167 | let values: (Key | null)[] = Array.isArray(state.value) ? state.value : [state.value]; |
| 168 | |
| 169 | // If used in a <form>, use a hidden input so the value can be submitted to a server. |
| 170 | // If the collection isn't too big, use a hidden <select> element for this so that browser |
| 171 | // autofill will work. Otherwise, use an <input type="hidden">. |
| 172 | if (state.collection.size <= 300) { |
| 173 | return ( |
| 174 | <div {...containerProps} data-testid="hidden-select-container"> |
| 175 | <label> |
| 176 | {label} |
| 177 | <select {...selectProps} ref={selectRef}> |
| 178 | <option value="" label={'\u00A0'}> |
| 179 | {'\u00A0'} |
| 180 | </option> |
| 181 | {[...state.collection.getKeys()].map(key => { |
| 182 | let item = state.collection.getItem(key); |
| 183 | if (item && item.type === 'item') { |
| 184 | return ( |
| 185 | <option key={item.key} value={item.key}> |
| 186 | {item.textValue} |
| 187 | </option> |
| 188 | ); |
| 189 | } |
| 190 | })} |
| 191 | {/* The collection may be empty during the initial render. */} |
| 192 | {/* Rendering options for the current values ensures the select has a value immediately, */} |
| 193 | {/* making FormData reads consistent. */} |
| 194 | {state.collection.size === 0 && |
| 195 | name && |
| 196 | values.map((value, i) => <option key={i} value={value ?? ''} />)} |
| 197 | </select> |
| 198 | </label> |
| 199 | </div> |
| 200 | ); |
| 201 | } else if (name) { |
| 202 | let data = selectData.get(state) || {}; |
| 203 | let {validationBehavior} = data; |
| 204 | |
| 205 | // Always render at least one hidden input to ensure required form submission. |
| 206 | if (values.length === 0) { |
| 207 | values = [null]; |
| 208 | } |
| 209 | |
| 210 | let res = values.map((value, i) => { |
| 211 | let inputProps: InputHTMLAttributes<HTMLInputElement> = { |
| 212 | type: 'hidden', |
nothing calls this directly
no test coverage detected