@instructure/ui-select 8.13.1-snapshot.9 → 8.14.1-snapshot.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/es/Select/Group/index.js +2 -3
  3. package/es/Select/Group/props.js +0 -7
  4. package/es/Select/Option/index.js +2 -2
  5. package/es/Select/Option/props.js +0 -27
  6. package/es/Select/SelectLocator.js +5 -2
  7. package/es/Select/index.js +92 -85
  8. package/es/Select/props.js +2 -142
  9. package/lib/Select/Group/index.js +2 -3
  10. package/lib/Select/Group/props.js +0 -7
  11. package/lib/Select/Option/index.js +2 -2
  12. package/lib/Select/Option/props.js +0 -27
  13. package/lib/Select/SelectLocator.js +3 -0
  14. package/lib/Select/index.js +96 -86
  15. package/lib/Select/props.js +2 -142
  16. package/package.json +23 -23
  17. package/src/Select/Group/index.tsx +2 -3
  18. package/src/Select/Group/props.ts +8 -8
  19. package/src/Select/Option/index.tsx +2 -2
  20. package/src/Select/Option/props.ts +33 -25
  21. package/src/Select/index.tsx +160 -168
  22. package/src/Select/props.ts +176 -117
  23. package/tsconfig.build.json +27 -2
  24. package/tsconfig.build.tsbuildinfo +1 -0
  25. package/types/Select/Group/index.d.ts +4 -5
  26. package/types/Select/Group/index.d.ts.map +1 -1
  27. package/types/Select/Group/props.d.ts +7 -1
  28. package/types/Select/Group/props.d.ts.map +1 -1
  29. package/types/Select/Option/index.d.ts +3 -7
  30. package/types/Select/Option/index.d.ts.map +1 -1
  31. package/types/Select/Option/props.d.ts +28 -4
  32. package/types/Select/Option/props.d.ts.map +1 -1
  33. package/types/Select/SelectLocator.d.ts +117 -117
  34. package/types/Select/index.d.ts +68 -99
  35. package/types/Select/index.d.ts.map +1 -1
  36. package/types/Select/props.d.ts +146 -21
  37. package/types/Select/props.d.ts.map +1 -1
@@ -23,10 +23,11 @@
23
23
  */
24
24
 
25
25
  /** @jsx jsx */
26
- import { Children, Component } from 'react'
26
+ import React, { Children, Component } from 'react'
27
27
 
28
28
  import { createChainedFunction } from '@instructure/ui-utils'
29
29
  import { testable } from '@instructure/ui-testable'
30
+ import { uid } from '@instructure/uid'
30
31
  import {
31
32
  matchComponentTypes,
32
33
  omitProps,
@@ -46,7 +47,17 @@ import {
46
47
  IconArrowOpenDownLine,
47
48
  IconArrowOpenUpLine
48
49
  } from '@instructure/ui-icons'
49
- import { uid } from '@instructure/uid'
50
+
51
+ import type { ViewProps } from '@instructure/ui-view'
52
+ import type { TextInputProps } from '@instructure/ui-text-input'
53
+ import type {
54
+ OptionsItemProps,
55
+ OptionsSeparatorProps
56
+ } from '@instructure/ui-options'
57
+ import type {
58
+ SelectableProps,
59
+ SelectableRender
60
+ } from '@instructure/ui-selectable'
50
61
 
51
62
  import { withStyle, jsx } from '@instructure/emotion'
52
63
 
@@ -55,6 +66,9 @@ import generateComponentTheme from './theme'
55
66
 
56
67
  import { Group } from './Group'
57
68
  import { Option } from './Option'
69
+
70
+ import type { RenderSelectOptionLabel } from './Option/props'
71
+
58
72
  import type { SelectProps } from './props'
59
73
  import { allowedProps, propTypes } from './props'
60
74
 
@@ -63,6 +77,7 @@ import { allowedProps, propTypes } from './props'
63
77
  category: components
64
78
  tags: autocomplete, typeahead, combobox, dropdown, search, form
65
79
  ---
80
+ @tsProps
66
81
  **/
67
82
  @withStyle(generateStyle, generateComponentTheme)
68
83
  @testable()
@@ -76,7 +91,6 @@ class Select extends Component<SelectProps> {
76
91
  inputValue: '',
77
92
  isShowingOptions: false,
78
93
  size: 'medium',
79
- placeholder: null,
80
94
  // Leave interaction default undefined so that `disabled` and `readOnly` can also be supplied
81
95
  interaction: undefined,
82
96
  isRequired: false,
@@ -84,33 +98,12 @@ class Select extends Component<SelectProps> {
84
98
  visibleOptionsCount: 8,
85
99
  placement: 'bottom stretch',
86
100
  constrain: 'window',
87
- // @ts-expect-error ts-migrate(6133) FIXME: 'event' is declared but its value is never read.
88
- onFocus: (event) => {},
89
- // @ts-expect-error ts-migrate(6133) FIXME: 'event' is declared but its value is never read.
90
- onBlur: (event) => {},
91
- // @ts-expect-error ts-migrate(6133) FIXME: 'event' is declared but its value is never read.
92
- onRequestShowOptions: (event) => {},
93
- // @ts-expect-error ts-migrate(6133) FIXME: 'event' is declared but its value is never read.
94
- onRequestHideOptions: (event) => {},
95
- // @ts-expect-error ts-migrate(6133) FIXME: 'event' is declared but its value is never read.
96
- onRequestHighlightOption: (event, data) => {},
97
- // @ts-expect-error ts-migrate(6133) FIXME: 'event' is declared but its value is never read.
98
- onRequestSelectOption: (event, data) => {},
99
- // @ts-expect-error ts-migrate(6133) FIXME: 'node' is declared but its value is never read.
100
- inputRef: (node) => {},
101
- // @ts-expect-error ts-migrate(6133) FIXME: 'node' is declared but its value is never read.
102
- listRef: (node) => {},
103
- renderBeforeInput: null,
104
- renderAfterInput: null,
105
- children: null,
106
101
  shouldNotWrap: false
107
102
  }
108
103
 
109
104
  static Option = Option
110
105
  static Group = Group
111
106
 
112
- ref: Element | null = null
113
-
114
107
  componentDidMount() {
115
108
  this.props.makeStyles?.()
116
109
  }
@@ -126,19 +119,20 @@ class Select extends Component<SelectProps> {
126
119
  hasInputRef: false
127
120
  }
128
121
 
129
- _defaultId = uid('Select')
130
- _assistId = uid('Select-assistiveText')
131
- _inputContainer = undefined
132
- _list = null
122
+ ref: HTMLInputElement | null = null
123
+
124
+ private _defaultId = uid('Select')
125
+ private _inputContainer: HTMLSpanElement | null = null
126
+ private _listView: Element | null = null
133
127
  // temporarily stores actionable options
134
- _optionIds = []
128
+ private _optionIds: string[] = []
135
129
  // best guess for first calculation of list height
136
- _optionHeight = 36
130
+ private _optionHeight = 36
137
131
 
138
132
  focus() {
139
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
140
133
  this.ref && this.ref.focus()
141
134
  }
135
+
142
136
  get _input() {
143
137
  console.warn(
144
138
  '_input property is deprecated and will be removed in v9, please use ref instead'
@@ -156,34 +150,31 @@ class Select extends Component<SelectProps> {
156
150
  }
157
151
 
158
152
  get width() {
159
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
160
- return this._inputContainer && this._inputContainer.offsetWidth
153
+ return this._inputContainer ? this._inputContainer.offsetWidth : undefined
161
154
  }
162
155
 
163
156
  get interaction() {
164
157
  return getInteraction({ props: this.props })
165
158
  }
166
159
 
167
- get highlightedOptionId() {
168
- let highlightedOptionId = null
160
+ get highlightedOptionId(): string | undefined {
161
+ let highlightedOptionId: string | undefined
162
+
169
163
  Children.toArray(this.props.children).forEach((child) => {
170
164
  if (matchComponentTypes(child, [Group])) {
171
165
  // group found
172
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
173
- Children.toArray(child.props.children).forEach((option) => {
166
+ ;(
167
+ Children.toArray((child as Group).props.children) as Option[]
168
+ ).forEach((option) => {
174
169
  // check options in group
175
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
176
170
  if (option.props.isHighlighted) {
177
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
178
171
  highlightedOptionId = option.props.id
179
172
  }
180
173
  })
181
174
  } else {
182
175
  // ungrouped option found
183
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
184
- if (child.props.isHighlighted) {
185
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
186
- highlightedOptionId = child.props.id
176
+ if ((child as Option).props.isHighlighted) {
177
+ highlightedOptionId = (child as Option).props.id
187
178
  }
188
179
  }
189
180
  })
@@ -192,102 +183,89 @@ class Select extends Component<SelectProps> {
192
183
  }
193
184
 
194
185
  get selectedOptionId() {
195
- // @ts-expect-error ts-migrate(7034) FIXME: Variable 'selectedOptionId' implicitly has type 'a... Remove this comment to see the full error message
196
- const selectedOptionId = []
186
+ const selectedOptionId: string[] = []
187
+
197
188
  Children.toArray(this.props.children).forEach((child) => {
198
189
  if (matchComponentTypes(child, [Group])) {
199
190
  // group found
200
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
201
- Children.toArray(child.props.children).forEach((option) => {
191
+ ;(
192
+ Children.toArray((child as Group).props.children) as Option[]
193
+ ).forEach((option) => {
202
194
  // check options in group
203
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
204
195
  if (option.props.isSelected) {
205
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
206
196
  selectedOptionId.push(option.props.id)
207
197
  }
208
198
  })
209
199
  } else {
210
200
  // ungrouped option found
211
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
212
- if (child.props.isSelected) {
213
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
214
- selectedOptionId.push(child.props.id)
201
+ if ((child as Option).props.isSelected) {
202
+ selectedOptionId.push((child as Option).props.id)
215
203
  }
216
204
  }
217
205
  })
218
206
 
219
- // @ts-expect-error ts-migrate(7005) FIXME: Variable 'selectedOptionId' implicitly has an 'any... Remove this comment to see the full error message
220
- if (selectedOptionId.length === 1) return selectedOptionId[0]
221
- if (selectedOptionId.length === 0) return null
222
- // @ts-expect-error ts-migrate(7005) FIXME: Variable 'selectedOptionId' implicitly has an 'any... Remove this comment to see the full error message
207
+ if (selectedOptionId.length === 1) {
208
+ return selectedOptionId[0]
209
+ }
210
+ if (selectedOptionId.length === 0) {
211
+ return undefined
212
+ }
223
213
  return selectedOptionId
224
214
  }
225
215
 
226
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'node' implicitly has an 'any' type.
227
- handleInputRef = (node) => {
216
+ handleInputRef = (node: HTMLInputElement | null) => {
228
217
  // ensures list is positioned with respect to input if list is open on mount
229
218
  if (!this.state.hasInputRef) {
230
219
  this.setState({ hasInputRef: true })
231
220
  }
232
221
 
233
222
  this.ref = node
234
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
235
- this.props.inputRef(node)
223
+ this.props.inputRef?.(node)
236
224
  }
237
225
 
238
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'node' implicitly has an 'any' type.
239
- handleListRef = (node) => {
240
- this._list = node
241
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
242
- this.props.listRef(node)
226
+ handleListRef = (node: HTMLUListElement | null) => {
227
+ this.props.listRef?.(node)
243
228
 
244
229
  // store option height to calculate list maxHeight
245
230
  if (node && node.querySelector('[role="option"]')) {
246
- this._optionHeight = node.querySelector('[role="option"]').offsetHeight
231
+ this._optionHeight = (
232
+ node.querySelector('[role="option"]') as HTMLElement
233
+ ).offsetHeight
247
234
  }
248
235
  }
249
236
 
250
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'node' implicitly has an 'any' type.
251
- handleInputContainerRef = (node) => {
237
+ handleInputContainerRef = (node: HTMLSpanElement | null) => {
252
238
  this._inputContainer = node
253
239
  }
254
240
 
255
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'id' implicitly has an 'any' type.
256
- scrollToOption(id) {
257
- // @ts-expect-error ts-migrate(2339) FIXME: Property '_listView' does not exist on type 'Selec... Remove this comment to see the full error message
241
+ scrollToOption(id?: string) {
258
242
  if (this._listView) {
259
- // @ts-expect-error ts-migrate(2339) FIXME: Property '_listView' does not exist on type 'Selec... Remove this comment to see the full error message
260
243
  const option = this._listView.querySelector(`[id="${id}"]`)
261
244
  if (!option) return
262
245
 
263
246
  const listItem = option.parentNode
264
- // @ts-expect-error ts-migrate(2339) FIXME: Property '_listView' does not exist on type 'Selec... Remove this comment to see the full error message
265
247
  const parentTop = getBoundingClientRect(this._listView).top
266
248
  const elemTop = getBoundingClientRect(listItem).top
267
- // @ts-expect-error ts-migrate(2339) FIXME: Property '_listView' does not exist on type 'Selec... Remove this comment to see the full error message
268
249
  const parentBottom = parentTop + this._listView.clientHeight
269
- const elemBottom = elemTop + listItem.clientHeight
250
+ const elemBottom =
251
+ elemTop + (listItem ? (listItem as Element).clientHeight : 0)
270
252
 
271
253
  if (elemBottom > parentBottom) {
272
- // @ts-expect-error ts-migrate(2339) FIXME: Property '_listView' does not exist on type 'Selec... Remove this comment to see the full error message
273
254
  this._listView.scrollTop += elemBottom - parentBottom
274
255
  } else if (elemTop < parentTop) {
275
- // @ts-expect-error ts-migrate(2339) FIXME: Property '_listView' does not exist on type 'Selec... Remove this comment to see the full error message
276
256
  this._listView.scrollTop -= parentTop - elemTop
277
257
  }
278
258
  }
279
259
  }
280
260
 
281
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
282
- highlightOption(event, id) {
261
+ highlightOption(event: React.SyntheticEvent, id: string) {
283
262
  const { onRequestHighlightOption } = this.props
284
263
  if (id) {
285
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
286
- onRequestHighlightOption(event, { id })
264
+ onRequestHighlightOption?.(event, { id })
287
265
  }
288
266
  }
289
267
 
290
- getEventHandlers() {
268
+ getEventHandlers(): Partial<SelectableProps> {
291
269
  const {
292
270
  isShowingOptions,
293
271
  onRequestShowOptions,
@@ -300,28 +278,23 @@ class Select extends Component<SelectProps> {
300
278
 
301
279
  return this.interaction === 'enabled'
302
280
  ? {
303
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
304
281
  onRequestShowOptions: (event) => {
305
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
306
- onRequestShowOptions(event)
282
+ onRequestShowOptions?.(event)
307
283
  if (selectedOptionId && !Array.isArray(selectedOptionId)) {
308
284
  // highlight selected option on show
309
285
  this.highlightOption(event, selectedOptionId)
310
286
  }
311
287
  },
312
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
313
288
  onRequestHideOptions: (event) => {
314
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
315
- onRequestHideOptions(event)
289
+ onRequestHideOptions?.(event)
316
290
  },
317
291
  onRequestHighlightOption: (
318
- event: Event,
292
+ event,
319
293
  { id, direction }: { id?: string; direction?: number }
320
294
  ) => {
321
295
  if (!isShowingOptions) return
322
296
  // if id exists, use that
323
- // @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'any' is not assignable to parame... Remove this comment to see the full error message
324
- let highlightId = this._optionIds.indexOf(id) > -1 ? id : null
297
+ let highlightId = this._optionIds.indexOf(id!) > -1 ? id : undefined
325
298
  if (!highlightId) {
326
299
  if (!highlightedOptionId) {
327
300
  // nothing highlighted yet, highlight first option
@@ -330,7 +303,7 @@ class Select extends Component<SelectProps> {
330
303
  // find next id based on direction
331
304
  const index = this._optionIds.indexOf(highlightedOptionId)
332
305
  highlightId =
333
- index > -1 ? this._optionIds[index + direction!] : null
306
+ index > -1 ? this._optionIds[index + direction!] : undefined
334
307
  }
335
308
  }
336
309
  if (highlightId) {
@@ -338,31 +311,29 @@ class Select extends Component<SelectProps> {
338
311
  this.highlightOption(event, highlightId)
339
312
  }
340
313
  },
341
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
342
314
  onRequestHighlightFirstOption: (event) => {
343
315
  this.highlightOption(event, this._optionIds[0])
344
316
  },
345
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
346
317
  onRequestHighlightLastOption: (event) => {
347
318
  this.highlightOption(
348
319
  event,
349
320
  this._optionIds[this._optionIds.length - 1]
350
321
  )
351
322
  },
352
- onRequestSelectOption: (event: Event, { id }: { id?: string }) => {
353
- // @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'any' is not assignable to parame... Remove this comment to see the full error message
323
+ onRequestSelectOption: (event, { id }) => {
354
324
  if (id && this._optionIds.indexOf(id) !== -1) {
355
325
  // only select if id exists as a valid option
356
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
357
- onRequestSelectOption(event, { id })
326
+ onRequestSelectOption?.(event, { id })
358
327
  }
359
328
  }
360
329
  }
361
330
  : {}
362
331
  }
363
332
 
364
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'option' implicitly has an 'any' type.
365
- renderOption(option, data) {
333
+ renderOption(
334
+ option: Option,
335
+ data: Pick<SelectableRender, 'getOptionProps' | 'getDisabledOptionProps'>
336
+ ) {
366
337
  const { getOptionProps, getDisabledOptionProps } = data
367
338
  const {
368
339
  id,
@@ -374,19 +345,21 @@ class Select extends Component<SelectProps> {
374
345
  children
375
346
  } = option.props
376
347
 
377
- const getRenderLabel = (renderLabel: any) => {
378
- return typeof renderLabel === 'function'
379
- ? renderLabel.bind(null, {
348
+ const getRenderOptionLabel = (
349
+ renderOptionLabel: RenderSelectOptionLabel
350
+ ): React.ReactNode => {
351
+ return typeof renderOptionLabel === 'function'
352
+ ? renderOptionLabel.bind(null, {
380
353
  id,
381
354
  isDisabled,
382
355
  isSelected,
383
356
  isHighlighted,
384
357
  children
385
358
  })
386
- : renderLabel
359
+ : renderOptionLabel
387
360
  }
388
361
 
389
- let optionProps = {
362
+ let optionProps: Partial<OptionsItemProps> = {
390
363
  // passthrough props
391
364
  ...omitProps(option.props, [
392
365
  ...Option.allowedProps,
@@ -395,8 +368,8 @@ class Select extends Component<SelectProps> {
395
368
  // props from selectable
396
369
  ...getOptionProps({ id }),
397
370
  // Options.Item props
398
- renderBeforeLabel: getRenderLabel(renderBeforeLabel),
399
- renderAfterLabel: getRenderLabel(renderAfterLabel)
371
+ renderBeforeLabel: getRenderOptionLabel(renderBeforeLabel),
372
+ renderAfterLabel: getRenderOptionLabel(renderAfterLabel)
400
373
  }
401
374
  // should option be treated as highlighted or selected
402
375
  if (isSelected) {
@@ -410,15 +383,23 @@ class Select extends Component<SelectProps> {
410
383
  optionProps = { ...optionProps, ...getDisabledOptionProps() }
411
384
  } else {
412
385
  // track as valid option if not disabled
413
- // @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'any' is not assignable to parame... Remove this comment to see the full error message
414
386
  this._optionIds.push(id)
415
387
  }
416
388
 
417
389
  return <Options.Item {...optionProps}>{children}</Options.Item>
418
390
  }
419
391
 
420
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'group' implicitly has an 'any' type.
421
- renderGroup(group, data) {
392
+ renderGroup(
393
+ group: Group,
394
+ data: Pick<
395
+ SelectableRender,
396
+ 'getOptionProps' | 'getDisabledOptionProps'
397
+ > & {
398
+ isFirstChild: boolean
399
+ isLastChild: boolean
400
+ afterGroup: boolean
401
+ }
402
+ ) {
422
403
  const {
423
404
  getOptionProps,
424
405
  getDisabledOptionProps,
@@ -427,7 +408,10 @@ class Select extends Component<SelectProps> {
427
408
  afterGroup
428
409
  } = data
429
410
  const { id, renderLabel, children, ...rest } = group.props
430
- const groupChildren = []
411
+ const groupChildren: (
412
+ | React.ReactElement<OptionsItemProps>
413
+ | React.ReactElement<OptionsSeparatorProps>
414
+ )[] = []
431
415
  // add a separator above
432
416
  if (!isFirstChild && !afterGroup) {
433
417
  groupChildren.push(<Options.Separator />)
@@ -442,7 +426,7 @@ class Select extends Component<SelectProps> {
442
426
  renderLabel={renderLabel}
443
427
  {...omitProps(rest, [...Options.allowedProps, ...Group.allowedProps])}
444
428
  >
445
- {Children.map(children, (child) => {
429
+ {Children.map(children as Option[], (child) => {
446
430
  return this.renderOption(child, {
447
431
  getOptionProps,
448
432
  getDisabledOptionProps
@@ -458,53 +442,50 @@ class Select extends Component<SelectProps> {
458
442
  return groupChildren
459
443
  }
460
444
 
461
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'data' implicitly has an 'any' type.
462
- renderList(data) {
445
+ renderList(
446
+ data: Pick<
447
+ SelectableRender,
448
+ 'getListProps' | 'getOptionProps' | 'getDisabledOptionProps'
449
+ >
450
+ ) {
463
451
  const { getListProps, getOptionProps, getDisabledOptionProps } = data
464
- const {
465
- isShowingOptions,
466
- optionsMaxWidth,
467
- visibleOptionsCount,
468
- children
469
- } = this.props
452
+ const { isShowingOptions, optionsMaxWidth, visibleOptionsCount, children } =
453
+ this.props
470
454
 
471
455
  let lastWasGroup = false
472
- const viewProps = isShowingOptions
456
+
457
+ const viewProps: Partial<ViewProps> = isShowingOptions
473
458
  ? {
474
459
  display: 'block',
475
460
  overflowY: 'auto',
476
- // @ts-expect-error ts-migrate(2532) FIXME: Object is possibly 'undefined'.
477
- maxHeight: this._optionHeight * visibleOptionsCount,
461
+ maxHeight: this._optionHeight * visibleOptionsCount!,
478
462
  maxWidth: optionsMaxWidth || this.width,
479
463
  background: 'primary',
480
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'node' implicitly has an 'any' type.
481
- elementRef: (node) => (this._listView = node)
464
+ elementRef: (node: Element | null) => (this._listView = node)
482
465
  }
483
466
  : { maxHeight: 0 }
484
467
 
485
468
  return (
486
- //@ts-expect-error TODO: fix this
487
469
  <View {...viewProps}>
488
470
  <Options
489
471
  {...getListProps({ as: 'ul', elementRef: this.handleListRef })}
490
472
  >
491
473
  {isShowingOptions
492
- ? // @ts-expect-error ts-migrate(7030) FIXME: Not all code paths return a value.
493
- Children.map(children, (child, index) => {
474
+ ? Children.map(children, (child, index) => {
494
475
  if (!child || !matchComponentTypes(child, [Group, Option])) {
495
476
  return // ignore invalid children
496
477
  }
497
478
  if (matchComponentTypes(child, [Option])) {
498
479
  lastWasGroup = false
499
- return this.renderOption(child, {
480
+ return this.renderOption(child as Option, {
500
481
  getOptionProps,
501
482
  getDisabledOptionProps
502
483
  })
503
484
  }
504
485
  if (matchComponentTypes(child, [Group])) {
505
- const afterGroup = lastWasGroup ? true : false
486
+ const afterGroup = lastWasGroup
506
487
  lastWasGroup = true
507
- return this.renderGroup(child, {
488
+ return this.renderGroup(child as Group, {
508
489
  getOptionProps,
509
490
  getDisabledOptionProps,
510
491
  // for rendering separators appropriately
@@ -513,6 +494,7 @@ class Select extends Component<SelectProps> {
513
494
  afterGroup
514
495
  })
515
496
  }
497
+ return
516
498
  })
517
499
  : null}
518
500
  </Options>
@@ -533,8 +515,9 @@ class Select extends Component<SelectProps> {
533
515
  )
534
516
  }
535
517
 
536
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'data' implicitly has an 'any' type.
537
- renderInput(data) {
518
+ renderInput(
519
+ data: Pick<SelectableRender, 'getInputProps' | 'getTriggerProps'>
520
+ ) {
538
521
  const { getInputProps, getTriggerProps } = data
539
522
  const {
540
523
  renderLabel,
@@ -560,51 +543,60 @@ class Select extends Component<SelectProps> {
560
543
  const passthroughProps = omitProps(rest, Select.allowedProps)
561
544
  const { ref, ...triggerProps } = getTriggerProps({ ...passthroughProps })
562
545
  const isEditable = typeof onInputChange !== 'undefined'
546
+
563
547
  // props to ensure screen readers treat uneditable selects as accessible
564
548
  // popup buttons rather than comboboxes.
565
- const overrideProps = !isEditable
549
+ const overrideProps: Partial<TextInputProps> = !isEditable
566
550
  ? {
567
551
  role: 'button',
568
552
  title: inputValue,
569
- 'aria-autocomplete': null
553
+ 'aria-autocomplete': undefined
570
554
  }
571
555
  : {}
556
+
572
557
  // backdoor to autocomplete attr to work around chrome autofill issues
573
558
  if (passthroughProps['autoComplete']) {
574
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'autoComplete' does not exist on type '{ ... Remove this comment to see the full error message
575
559
  overrideProps.autoComplete = passthroughProps['autoComplete']
576
560
  }
577
561
 
578
- return (
579
- <TextInput
580
- {...triggerProps}
581
- {...getInputProps({
582
- id: this.id,
583
- renderLabel,
584
- placeholder,
585
- size,
586
- width,
587
- htmlSize,
588
- messages,
589
- value: inputValue,
590
- inputRef: createChainedFunction(ref, this.handleInputRef),
591
- inputContainerRef: this.handleInputContainerRef,
592
- interaction:
593
- interaction === 'enabled' && !isEditable
594
- ? 'readonly' // prevent keyboard cursor
595
- : interaction,
596
- isRequired,
597
- shouldNotWrap,
598
- display: isInline ? 'inline-block' : 'block',
599
- renderBeforeInput,
600
- renderAfterInput: renderAfterInput || this.renderIcon(),
601
- onChange: onInputChange,
602
- onFocus,
603
- onBlur: createChainedFunction(onBlur, onRequestHideOptions),
604
- ...overrideProps
605
- })}
606
- />
607
- )
562
+ const inputProps: Partial<TextInputProps> = {
563
+ id: this.id,
564
+ renderLabel,
565
+ placeholder,
566
+ size,
567
+ width,
568
+ htmlSize,
569
+ messages,
570
+ value: inputValue,
571
+ inputRef: createChainedFunction(ref, this.handleInputRef),
572
+ inputContainerRef: this.handleInputContainerRef,
573
+ interaction:
574
+ interaction === 'enabled' && !isEditable
575
+ ? 'readonly' // prevent keyboard cursor
576
+ : interaction,
577
+ isRequired,
578
+ shouldNotWrap,
579
+ display: isInline ? 'inline-block' : 'block',
580
+ renderBeforeInput,
581
+ renderAfterInput: renderAfterInput || this.renderIcon(),
582
+
583
+ // If `inputValue` is provided, we need to pass a default onChange handler,
584
+ // because TextInput `value` is a controlled prop,
585
+ // and onChange is not required for Select
586
+ // (before it was handled by TextInput's defaultProp)
587
+ onChange:
588
+ typeof onInputChange === 'function'
589
+ ? onInputChange
590
+ : inputValue
591
+ ? () => {}
592
+ : undefined,
593
+
594
+ onFocus,
595
+ onBlur: createChainedFunction(onBlur, onRequestHideOptions),
596
+ ...overrideProps
597
+ }
598
+
599
+ return <TextInput {...triggerProps} {...getInputProps(inputProps)} />
608
600
  }
609
601
 
610
602
  render() {
@@ -626,7 +618,7 @@ class Select extends Component<SelectProps> {
626
618
  <Selectable
627
619
  highlightedOptionId={highlightedOptionId}
628
620
  isShowingOptions={isShowingOptions}
629
- selectedOptionId={selectedOptionId ? selectedOptionId : null}
621
+ selectedOptionId={selectedOptionId}
630
622
  {...this.getEventHandlers()}
631
623
  >
632
624
  {({