@instructure/ui-selectable 10.4.2-snapshot-11 → 10.4.2-snapshot-13

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/CHANGELOG.md CHANGED
@@ -3,7 +3,7 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [10.4.2-snapshot-11](https://github.com/instructure/instructure-ui/compare/v10.4.1...v10.4.2-snapshot-11) (2024-11-06)
6
+ ## [10.4.2-snapshot-13](https://github.com/instructure/instructure-ui/compare/v10.4.1...v10.4.2-snapshot-13) (2024-11-07)
7
7
 
8
8
  **Note:** Version bump only for package @instructure/ui-selectable
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-selectable",
3
- "version": "10.4.2-snapshot-11",
3
+ "version": "10.4.2-snapshot-13",
4
4
  "description": "A UI component library made by Instructure Inc.",
5
5
  "author": "Instructure, Inc. Engineering and Product Design",
6
6
  "module": "./es/index.js",
@@ -23,17 +23,17 @@
23
23
  },
24
24
  "license": "MIT",
25
25
  "devDependencies": {
26
- "@instructure/ui-babel-preset": "10.4.2-snapshot-11",
27
- "@instructure/ui-test-utils": "10.4.2-snapshot-11"
26
+ "@instructure/ui-babel-preset": "10.4.2-snapshot-13",
27
+ "@instructure/ui-test-utils": "10.4.2-snapshot-13"
28
28
  },
29
29
  "dependencies": {
30
30
  "@babel/runtime": "^7.25.6",
31
- "@instructure/console": "10.4.2-snapshot-11",
32
- "@instructure/shared-types": "10.4.2-snapshot-11",
33
- "@instructure/ui-dom-utils": "10.4.2-snapshot-11",
34
- "@instructure/ui-react-utils": "10.4.2-snapshot-11",
35
- "@instructure/ui-testable": "10.4.2-snapshot-11",
36
- "@instructure/ui-utils": "10.4.2-snapshot-11",
31
+ "@instructure/console": "10.4.2-snapshot-13",
32
+ "@instructure/shared-types": "10.4.2-snapshot-13",
33
+ "@instructure/ui-dom-utils": "10.4.2-snapshot-13",
34
+ "@instructure/ui-react-utils": "10.4.2-snapshot-13",
35
+ "@instructure/ui-testable": "10.4.2-snapshot-13",
36
+ "@instructure/ui-utils": "10.4.2-snapshot-13",
37
37
  "keycode": "^2",
38
38
  "prop-types": "^15.8.1"
39
39
  },
@@ -4,153 +4,384 @@ describes: Selectable
4
4
 
5
5
  `Selectable` is a low level utility component that can be used to create combobox widgets. Before composing your own component, make sure an existing component, like [Select](#Select), can't be adapted for your use case.
6
6
 
7
- ```javascript
8
- ---
9
- type: example
10
- ---
11
-
12
- class CustomSelect extends React.Component {
13
- state = {
14
- isShowingOptions: false,
15
- highlightedOptionId: this.props.options[0].id,
16
- selectedOptionId: this.props.options[0].id,
17
- inputValue: this.props.options[0].label,
18
- filteredOptions: this.props.options
19
- }
7
+ - ```javascript
8
+ class CustomSelect extends React.Component {
9
+ state = {
10
+ isShowingOptions: false,
11
+ highlightedOptionId: this.props.options[0].id,
12
+ selectedOptionId: this.props.options[0].id,
13
+ inputValue: this.props.options[0].label,
14
+ filteredOptions: this.props.options
15
+ }
20
16
 
21
- filterOptions = (value) => {
22
- return this.props.options.filter(option => (
23
- option.label.toLowerCase().startsWith(value.toLowerCase())
24
- ))
25
- }
17
+ filterOptions = (value) => {
18
+ return this.props.options.filter((option) =>
19
+ option.label.toLowerCase().startsWith(value.toLowerCase())
20
+ )
21
+ }
26
22
 
27
- matchValue () {
28
- const { filteredOptions, inputValue, selectedOptionId } = this.state
29
- if (filteredOptions.length === 1) {
30
- if (filteredOptions[0].label.toLowerCase() === inputValue.toLowerCase()) {
31
- return {
32
- inputValue: filteredOptions[0].label,
33
- selectedOptionId: filteredOptions[0].id
23
+ matchValue() {
24
+ const { filteredOptions, inputValue, selectedOptionId } = this.state
25
+ if (filteredOptions.length === 1) {
26
+ if (
27
+ filteredOptions[0].label.toLowerCase() === inputValue.toLowerCase()
28
+ ) {
29
+ return {
30
+ inputValue: filteredOptions[0].label,
31
+ selectedOptionId: filteredOptions[0].id
32
+ }
34
33
  }
35
34
  }
35
+ const index = this.getOptionIndex(
36
+ null,
37
+ selectedOptionId,
38
+ this.props.options
39
+ )
40
+ return { inputValue: this.props.options[index].label }
36
41
  }
37
- const index = this.getOptionIndex(null, selectedOptionId, this.props.options)
38
- return { inputValue: this.props.options[index].label }
39
- }
40
42
 
41
- getInputStyles () {
42
- return {
43
- display: 'block',
44
- width: '250px',
45
- padding: '5px'
43
+ getInputStyles() {
44
+ return {
45
+ display: 'block',
46
+ width: '250px',
47
+ padding: '5px'
48
+ }
46
49
  }
47
- }
48
50
 
49
- getListStyles () {
50
- const { isShowingOptions } = this.state
51
- return {
52
- background: 'white',
53
- listStyle: 'none',
54
- padding: 0,
55
- margin: 0,
56
- border: isShowingOptions && 'solid 1px lightgray'
51
+ getListStyles() {
52
+ const { isShowingOptions } = this.state
53
+ return {
54
+ background: 'white',
55
+ listStyle: 'none',
56
+ padding: 0,
57
+ margin: 0,
58
+ border: isShowingOptions && 'solid 1px lightgray'
59
+ }
57
60
  }
58
- }
59
61
 
60
- getOptionStyles (option) {
61
- const { selectedOptionId, highlightedOptionId } = this.state
62
- const selected = selectedOptionId === option.id
63
- const highlighted = highlightedOptionId === option.id
64
- let background = 'transparent'
65
- if (selected) {
66
- background = 'lightgray'
67
- } else if (highlighted) {
68
- background = '#eeeeee'
69
- }
70
- return {
71
- background,
72
- padding: '0 10px'
62
+ getOptionStyles(option) {
63
+ const { selectedOptionId, highlightedOptionId } = this.state
64
+ const selected = selectedOptionId === option.id
65
+ const highlighted = highlightedOptionId === option.id
66
+ let background = 'transparent'
67
+ if (selected) {
68
+ background = 'lightgray'
69
+ } else if (highlighted) {
70
+ background = '#eeeeee'
71
+ }
72
+ return {
73
+ background,
74
+ padding: '0 10px'
75
+ }
73
76
  }
74
- }
75
77
 
76
- getOptionIndex (direction, id, from) {
77
- const { filteredOptions, highlightedOptionId } = this.state
78
- const options = from ? from : filteredOptions
79
- let index
80
-
81
- for (let i = 0; i <= options.length - 1; i++) {
82
- if (typeof id === 'undefined') {
83
- if (highlightedOptionId === options[i].id) {
84
- index = i + direction
85
- if (index < 0) {
86
- index = 0
87
- } else if (index >= options.length - 1) {
88
- index = options.length - 1
78
+ getOptionIndex(direction, id, from) {
79
+ const { filteredOptions, highlightedOptionId } = this.state
80
+ const options = from ? from : filteredOptions
81
+ let index
82
+
83
+ for (let i = 0; i <= options.length - 1; i++) {
84
+ if (typeof id === 'undefined') {
85
+ if (highlightedOptionId === options[i].id) {
86
+ index = i + direction
87
+ if (index < 0) {
88
+ index = 0
89
+ } else if (index >= options.length - 1) {
90
+ index = options.length - 1
91
+ }
92
+ break
93
+ }
94
+ } else {
95
+ if (id === options[i].id) {
96
+ index = i
97
+ break
89
98
  }
90
- break
91
- }
92
- } else {
93
- if (id === options[i].id) {
94
- index = i
95
- break
96
99
  }
97
100
  }
101
+ return index
102
+ }
103
+
104
+ getHandlers() {
105
+ return this.props.isDisabled
106
+ ? {}
107
+ : {
108
+ onRequestShowOptions: (e) =>
109
+ this.setState((state) => ({
110
+ isShowingOptions: true,
111
+ highlightedOptionId: state.filteredOptions[0].id
112
+ })),
113
+ onRequestHideOptions: (e) => {
114
+ const index = this.getOptionIndex(
115
+ null,
116
+ this.state.selectedOptionId,
117
+ this.props.options
118
+ )
119
+ this.setState((state) => ({
120
+ isShowingOptions: false,
121
+ inputValue: this.props.options[index].label,
122
+ filteredOptions: this.props.options,
123
+ highlightedOptionId: null
124
+ }))
125
+ },
126
+ onRequestHighlightOption: (e, { id, direction }) => {
127
+ let index = this.getOptionIndex(direction, id)
128
+ this.setState((state) => ({
129
+ highlightedOptionId: state.filteredOptions[index]
130
+ ? state.filteredOptions[index].id
131
+ : null,
132
+ inputValue:
133
+ direction && state.filteredOptions[index]
134
+ ? state.filteredOptions[index].label
135
+ : state.inputValue
136
+ }))
137
+ },
138
+ onRequestSelectOption: (e, { id }) => {
139
+ const index = this.getOptionIndex(null, id)
140
+ this.setState((state) => ({
141
+ selectedOptionId: id,
142
+ inputValue: state.filteredOptions[index].label,
143
+ filteredOptions: this.props.options,
144
+ isShowingOptions: false,
145
+ highlightedOptionId: null
146
+ }))
147
+ }
148
+ }
149
+ }
150
+
151
+ render() {
152
+ const {
153
+ isShowingOptions,
154
+ inputValue,
155
+ highlightedOptionId,
156
+ selectedOptionId,
157
+ filteredOptions
158
+ } = this.state
159
+
160
+ return (
161
+ <Selectable
162
+ isShowingOptions={isShowingOptions}
163
+ highlightedOptionId={highlightedOptionId}
164
+ selectedOptionId={selectedOptionId ? selectedOptionId : null}
165
+ {...this.getHandlers()}
166
+ >
167
+ {({
168
+ getRootProps,
169
+ getLabelProps,
170
+ getInputProps,
171
+ getTriggerProps,
172
+ getListProps,
173
+ getOptionProps
174
+ }) => (
175
+ <span
176
+ style={{ display: 'inline-block' }}
177
+ {...getRootProps({ ref: (el) => (this.rootRef = el) })}
178
+ >
179
+ <label {...getLabelProps()}>Selectable Example</label>
180
+ <input
181
+ style={this.getInputStyles()}
182
+ {...getInputProps()}
183
+ {...getTriggerProps({
184
+ type: 'text',
185
+ value: inputValue,
186
+ onChange: (e) => {
187
+ const newOptions = this.filterOptions(e.target.value)
188
+ this.setState({
189
+ inputValue: e.target.value,
190
+ filteredOptions: newOptions,
191
+ isShowingOptions: true,
192
+ highlightedOptionId: newOptions[0]
193
+ ? newOptions[0].id
194
+ : null
195
+ })
196
+ },
197
+ onBlur: (e) =>
198
+ this.setState({
199
+ filteredOptions: this.props.options,
200
+ highlightedOptionId: null,
201
+ isShowingOptions: false,
202
+ ...this.matchValue()
203
+ })
204
+ })}
205
+ />
206
+ <ul style={this.getListStyles()} {...getListProps()}>
207
+ {isShowingOptions &&
208
+ filteredOptions.map((option) => (
209
+ <li
210
+ key={option.id}
211
+ style={this.getOptionStyles(option)}
212
+ {...getOptionProps({ id: option.id })}
213
+ >
214
+ {option.label}
215
+ </li>
216
+ ))}
217
+ </ul>
218
+ </span>
219
+ )}
220
+ </Selectable>
221
+ )
98
222
  }
99
- return index
100
223
  }
101
224
 
102
- getHandlers () {
103
- return this.props.isDisabled ? {} : {
104
- onRequestShowOptions: (e) => this.setState(state => ({
105
- isShowingOptions: true,
106
- highlightedOptionId: state.filteredOptions[0].id
107
- })),
108
- onRequestHideOptions: (e) => {
109
- const index = this.getOptionIndex(null, this.state.selectedOptionId, this.props.options)
110
- this.setState(state => ({
111
- isShowingOptions: false,
112
- inputValue: this.props.options[index].label,
113
- filteredOptions: this.props.options,
114
- highlightedOptionId: null,
115
- }))
116
- },
117
- onRequestHighlightOption: (e, { id, direction }) => {
118
- let index = this.getOptionIndex(direction, id)
119
- this.setState(state => ({
120
- highlightedOptionId: state.filteredOptions[index] ? state.filteredOptions[index].id : null,
121
- inputValue: direction && state.filteredOptions[index]
122
- ? state.filteredOptions[index].label
123
- : state.inputValue
124
- }))
125
- },
126
- onRequestSelectOption: (e, { id }) => {
127
- const index = this.getOptionIndex(null, id)
128
- this.setState(state => ({
129
- selectedOptionId: id,
130
- inputValue: state.filteredOptions[index].label,
131
- filteredOptions: this.props.options,
132
- isShowingOptions: false,
133
- highlightedOptionId: null,
134
- }))
225
+ render(
226
+ <View>
227
+ <CustomSelect
228
+ options={[
229
+ { id: 'opt0', value: '0', label: 'Alabama' },
230
+ { id: 'opt1', value: '1', label: 'Alaska' },
231
+ { id: 'opt2', value: '2', label: 'American Samoa' },
232
+ { id: 'opt3', value: '3', label: 'Arizona' },
233
+ { id: 'opt4', value: '4', label: 'Arkansas' },
234
+ { id: 'opt5', value: '5', label: 'California' },
235
+ { id: 'opt6', value: '6', label: 'Colorado' },
236
+ { id: 'opt7', value: '7', label: 'Connecticut' },
237
+ { id: 'opt8', value: '8', label: 'Delaware' },
238
+ { id: 'opt9', value: '9', label: 'District Of Columbia' },
239
+ { id: 'opt10', value: '10', label: 'Federated States Of Micronesia' },
240
+ { id: 'opt11', value: '11', label: 'Florida' },
241
+ { id: 'opt12', value: '12', label: 'Georgia' },
242
+ { id: 'opt13', value: '13', label: 'Guam' },
243
+ { id: 'opt14', value: '14', label: 'Hawaii' },
244
+ { id: 'opt15', value: '15', label: 'Idaho' },
245
+ { id: 'opt16', value: '16', label: 'Illinois' }
246
+ ]}
247
+ />
248
+ </View>
249
+ )
250
+ ```
251
+
252
+ - ```js
253
+ const CustomSelect = ({ options, isDisabled }) => {
254
+ const [isShowingOptions, setIsShowingOptions] = useState(false)
255
+ const [highlightedOptionId, setHighlightedOptionId] = useState(
256
+ options[0].id
257
+ )
258
+ const [selectedOptionId, setSelectedOptionId] = useState(options[0].id)
259
+ const [inputValue, setInputValue] = useState(options[0].label)
260
+ const [filteredOptions, setFilteredOptions] = useState(options)
261
+
262
+ const rootRef = useRef(null)
263
+
264
+ const filterOptions = (value) => {
265
+ return options.filter((option) =>
266
+ option.label.toLowerCase().startsWith(value.toLowerCase())
267
+ )
268
+ }
269
+
270
+ const matchValue = () => {
271
+ if (filteredOptions.length === 1) {
272
+ if (
273
+ filteredOptions[0].label.toLowerCase() === inputValue.toLowerCase()
274
+ ) {
275
+ setInputValue(filteredOptions[0].label)
276
+ setsSelectedOptionId(filteredOptions[0].id)
277
+ return
278
+ }
135
279
  }
280
+ const index = getOptionIndex(null, selectedOptionId, options)
281
+ setInputValue(options[index].label)
282
+ }
283
+
284
+ const getInputStyles = () => {
285
+ return {
286
+ display: 'block',
287
+ width: '250px',
288
+ padding: '5px'
289
+ }
290
+ }
291
+
292
+ const getListStyles = () => {
293
+ return {
294
+ background: 'white',
295
+ listStyle: 'none',
296
+ padding: 0,
297
+ margin: 0,
298
+ border: isShowingOptions && 'solid 1px lightgray'
299
+ }
300
+ }
301
+
302
+ const getOptionStyles = (option) => {
303
+ const selected = selectedOptionId === option.id
304
+ const highlighted = highlightedOptionId === option.id
305
+ let background = 'transparent'
306
+ if (selected) {
307
+ background = 'lightgray'
308
+ } else if (highlighted) {
309
+ background = '#eeeeee'
310
+ }
311
+ return {
312
+ background,
313
+ padding: '0 10px'
314
+ }
315
+ }
316
+
317
+ const getOptionIndex = (direction, id, from) => {
318
+ const options = from ? from : filteredOptions
319
+ let index
320
+
321
+ for (let i = 0; i <= options.length - 1; i++) {
322
+ if (typeof id === 'undefined') {
323
+ if (highlightedOptionId === options[i].id) {
324
+ index = i + direction
325
+ if (index < 0) {
326
+ index = 0
327
+ } else if (index >= options.length - 1) {
328
+ index = options.length - 1
329
+ }
330
+ break
331
+ }
332
+ } else {
333
+ if (id === options[i].id) {
334
+ index = i
335
+ break
336
+ }
337
+ }
338
+ }
339
+ return index
136
340
  }
137
- }
138
341
 
139
- render () {
140
- const {
141
- isShowingOptions,
142
- inputValue,
143
- highlightedOptionId,
144
- selectedOptionId,
145
- filteredOptions
146
- } = this.state
342
+ const getHandlers = () => {
343
+ return isDisabled
344
+ ? {}
345
+ : {
346
+ onRequestShowOptions: (e) => {
347
+ setIsShowingOptions(true)
348
+ setHighlightedOptionId(filteredOptions[0].id)
349
+ },
350
+ onRequestHideOptions: (e) => {
351
+ const index = getOptionIndex(null, selectedOptionId, options)
352
+ setIsShowingOptions(false)
353
+ setInputValue(options[index].label)
354
+ setFilteredOptions(options)
355
+ setHighlightedOptionId(null)
356
+ },
357
+ onRequestHighlightOption: (e, { id, direction }) => {
358
+ let index = getOptionIndex(direction, id)
359
+ setHighlightedOptionId(
360
+ filteredOptions[index] ? filteredOptions[index].id : null
361
+ )
362
+ setInputValue(
363
+ direction && filteredOptions[index]
364
+ ? filteredOptions[index].label
365
+ : inputValue
366
+ )
367
+ },
368
+ onRequestSelectOption: (e, { id }) => {
369
+ const index = getOptionIndex(null, id)
370
+ setSelectedOptionId(id)
371
+ setInputValue(filteredOptions[index].label)
372
+ setFilteredOptions(options)
373
+ setIsShowingOptions(false)
374
+ setHighlightedOptionId(null)
375
+ }
376
+ }
377
+ }
147
378
 
148
379
  return (
149
380
  <Selectable
150
381
  isShowingOptions={isShowingOptions}
151
382
  highlightedOptionId={highlightedOptionId}
152
383
  selectedOptionId={selectedOptionId ? selectedOptionId : null}
153
- {...this.getHandlers()}
384
+ {...getHandlers()}
154
385
  >
155
386
  {({
156
387
  getRootProps,
@@ -161,80 +392,77 @@ class CustomSelect extends React.Component {
161
392
  getOptionProps
162
393
  }) => (
163
394
  <span
164
- style={{display: 'inline-block'}}
165
- {...getRootProps({ref: (el) => this.rootRef = el})}
395
+ style={{ display: 'inline-block' }}
396
+ {...getRootProps({ ref: rootRef })}
166
397
  >
167
398
  <label {...getLabelProps()}>Selectable Example</label>
168
399
  <input
169
- style={this.getInputStyles()}
400
+ style={getInputStyles()}
170
401
  {...getInputProps()}
171
402
  {...getTriggerProps({
172
403
  type: 'text',
173
404
  value: inputValue,
174
405
  onChange: (e) => {
175
- const newOptions = this.filterOptions(e.target.value)
176
- this.setState({
177
- inputValue: e.target.value,
178
- filteredOptions: newOptions,
179
- isShowingOptions: true,
180
- highlightedOptionId: newOptions[0] ? newOptions[0].id : null
181
- })
406
+ const newOptions = filterOptions(e.target.value)
407
+ setInputValue(e.target.valu)
408
+ setFilteredOptions(newOptions)
409
+ setIsShowingOptions(true)
410
+ setHighlightedOptionId(
411
+ newOptions[0] ? newOptions[0].id : null
412
+ )
182
413
  },
183
- onBlur: (e) => this.setState({
184
- filteredOptions: this.props.options,
185
- highlightedOptionId: null,
186
- isShowingOptions: false,
187
- ...this.matchValue()
188
- })
189
- })
190
- } />
191
- <ul
192
- style={this.getListStyles()}
193
- {...getListProps()}
194
- >
195
- {isShowingOptions && filteredOptions.map((option) => (
196
- <li
197
- key={option.id}
198
- style={this.getOptionStyles(option)}
199
- {...getOptionProps({ id: option.id })}
200
- >
201
- {option.label}
202
- </li>
203
- ))}
414
+ onBlur: (e) => {
415
+ setFilteredOptions(options)
416
+ setHighlightedOptionId(null)
417
+ setIsShowingOptions(false)
418
+ matchValue()
419
+ }
420
+ })}
421
+ />
422
+ <ul style={getListStyles()} {...getListProps()}>
423
+ {isShowingOptions &&
424
+ filteredOptions.map((option) => (
425
+ <li
426
+ key={option.id}
427
+ style={getOptionStyles(option)}
428
+ {...getOptionProps({ id: option.id })}
429
+ >
430
+ {option.label}
431
+ </li>
432
+ ))}
204
433
  </ul>
205
434
  </span>
206
435
  )}
207
436
  </Selectable>
208
437
  )
209
438
  }
210
- }
211
-
212
- render(
213
- <View>
214
- <CustomSelect
215
- options={[
216
- { id: 'opt0', value: '0', label: 'Alabama' },
217
- { id: 'opt1', value: '1', label: 'Alaska' },
218
- { id: 'opt2', value: '2', label: 'American Samoa' },
219
- { id: 'opt3', value: '3', label: 'Arizona' },
220
- { id: 'opt4', value: '4', label: 'Arkansas' },
221
- { id: 'opt5', value: '5', label: 'California' },
222
- { id: 'opt6', value: '6', label: 'Colorado' },
223
- { id: 'opt7', value: '7', label: 'Connecticut' },
224
- { id: 'opt8', value: '8', label: 'Delaware' },
225
- { id: 'opt9', value: '9', label: 'District Of Columbia' },
226
- { id: 'opt10', value: '10', label: 'Federated States Of Micronesia' },
227
- { id: 'opt11', value: '11', label: 'Florida' },
228
- { id: 'opt12', value: '12', label: 'Georgia' },
229
- { id: 'opt13', value: '13', label: 'Guam' },
230
- { id: 'opt14', value: '14', label: 'Hawaii' },
231
- { id: 'opt15', value: '15', label: 'Idaho' },
232
- { id: 'opt16', value: '16', label: 'Illinois' }
233
- ]}
234
- />
235
- </View>
236
- )
237
- ```
439
+
440
+ render(
441
+ <View>
442
+ <CustomSelect
443
+ options={[
444
+ { id: 'opt0', value: '0', label: 'Alabama' },
445
+ { id: 'opt1', value: '1', label: 'Alaska' },
446
+ { id: 'opt2', value: '2', label: 'American Samoa' },
447
+ { id: 'opt3', value: '3', label: 'Arizona' },
448
+ { id: 'opt4', value: '4', label: 'Arkansas' },
449
+ { id: 'opt5', value: '5', label: 'California' },
450
+ { id: 'opt6', value: '6', label: 'Colorado' },
451
+ { id: 'opt7', value: '7', label: 'Connecticut' },
452
+ { id: 'opt8', value: '8', label: 'Delaware' },
453
+ { id: 'opt9', value: '9', label: 'District Of Columbia' },
454
+ { id: 'opt10', value: '10', label: 'Federated States Of Micronesia' },
455
+ { id: 'opt11', value: '11', label: 'Florida' },
456
+ { id: 'opt12', value: '12', label: 'Georgia' },
457
+ { id: 'opt13', value: '13', label: 'Guam' },
458
+ { id: 'opt14', value: '14', label: 'Hawaii' },
459
+ { id: 'opt15', value: '15', label: 'Idaho' },
460
+ { id: 'opt16', value: '16', label: 'Illinois' }
461
+ ]}
462
+ />
463
+ </View>
464
+ )
465
+ ```
238
466
 
239
467
  Selectable has very few opinions about how a combobox component should be composed. It mostly aims to ensure all the proper WAI-ARIA roles and attributes are set on the right elements at the right times. Selectable uses a combination of controllable props and prop getters to set these attributes and provide accessible behavior.
240
468