, Dropdo
})
: Indicator.create(toggleIndicator, {
defaultProps: {
- direction: isOpen ? 'top' : 'bottom',
+ direction: open ? 'top' : 'bottom',
styles: styles.toggleIndicator,
},
overrideProps: (predefinedProps: IndicatorProps) => ({
@@ -367,7 +384,6 @@ class Dropdown extends AutoControlledComponent, Dropdo
{this.renderItemsList(
styles,
variables,
- isOpen,
highlightedIndex,
toggleMenu,
selectItemAtIndex,
@@ -458,7 +474,6 @@ class Dropdown extends AutoControlledComponent, Dropdo
private renderItemsList(
styles: ComponentSlotStylesInput,
variables: ComponentVariablesInput,
- isOpen: boolean,
highlightedIndex: number,
toggleMenu: () => void,
selectItemAtIndex: (index: number) => void,
@@ -467,6 +482,7 @@ class Dropdown extends AutoControlledComponent, Dropdo
getInputProps: (options?: GetInputPropsOptions) => any,
) {
const { search } = this.props
+ const { open } = this.state
const { innerRef, ...accessibilityMenuProps } = getMenuProps(
{ refKey: 'innerRef' },
{ suppressRefError: true },
@@ -501,8 +517,8 @@ class Dropdown extends AutoControlledComponent, Dropdo
{...accessibilityMenuProps}
styles={styles.list}
tabIndex={search ? undefined : -1} // needs to be focused when trigger button is activated.
- aria-hidden={!isOpen}
- items={isOpen ? this.renderItems(styles, variables, getItemProps, highlightedIndex) : []}
+ aria-hidden={!open}
+ items={open ? this.renderItems(styles, variables, getItemProps, highlightedIndex) : []}
/>
)
@@ -576,13 +592,7 @@ class Dropdown extends AutoControlledComponent, Dropdo
}
private handleSearchQueryChange = (searchQuery: string) => {
- this.trySetState({ searchQuery })
- _.invoke(
- this.props,
- 'onSearchQueryChange',
- {}, // we don't have event for it, but want to keep the event handling interface, event is empty.
- { ...this.props, searchQuery },
- )
+ this.trySetStateAndInvokeHandler('onSearchQueryChange', null, { searchQuery })
}
private handleDownshiftStateChanges = (
@@ -602,8 +612,8 @@ class Dropdown extends AutoControlledComponent, Dropdo
}
private handleStateChange = (changes: StateChangeOptions) => {
- if (changes.isOpen !== undefined && changes.isOpen !== this.state.isOpen) {
- this.setState({ isOpen: changes.isOpen })
+ if (changes.isOpen !== undefined && changes.isOpen !== this.state.open) {
+ this.trySetStateAndInvokeHandler('onOpenChange', null, { open: changes.isOpen })
}
if (changes.isOpen && !this.props.search) {
@@ -664,19 +674,18 @@ class Dropdown extends AutoControlledComponent, Dropdo
item: ShorthandValue,
rtl: boolean,
) => ({
- onRemove: (e: React.SyntheticEvent, DropdownSelectedItemProps: DropdownSelectedItemProps) => {
- this.handleSelectedItemRemove(e, item, predefinedProps, DropdownSelectedItemProps)
+ onRemove: (e: React.SyntheticEvent, dropdownSelectedItemProps: DropdownSelectedItemProps) => {
+ this.handleSelectedItemRemove(e, item, predefinedProps, dropdownSelectedItemProps)
},
- onClick: (e: React.SyntheticEvent, DropdownSelectedItemProps: DropdownSelectedItemProps) => {
+ onClick: (e: React.SyntheticEvent, dropdownSelectedItemProps: DropdownSelectedItemProps) => {
const { value } = this.state as { value: ShorthandCollection }
- this.trySetState({
- activeSelectedIndex: value.indexOf(item),
- })
+
+ this.trySetState({ activeSelectedIndex: value.indexOf(item) })
e.stopPropagation()
- _.invoke(predefinedProps, 'onClick', e, DropdownSelectedItemProps)
+ _.invoke(predefinedProps, 'onClick', e, dropdownSelectedItemProps)
},
- onKeyDown: (e: React.SyntheticEvent, DropdownSelectedItemProps: DropdownSelectedItemProps) => {
- this.handleSelectedItemKeyDown(e, item, predefinedProps, DropdownSelectedItemProps, rtl)
+ onKeyDown: (e: React.SyntheticEvent, dropdownSelectedItemProps: DropdownSelectedItemProps) => {
+ this.handleSelectedItemKeyDown(e, item, predefinedProps, dropdownSelectedItemProps, rtl)
},
})
@@ -846,12 +855,11 @@ class Dropdown extends AutoControlledComponent, Dropdo
private handleSelectedChange = (item: ShorthandValue) => {
const { items, multiple, getA11ySelectionMessage } = this.props
- const newState = {
+
+ this.trySetStateAndInvokeHandler('onSelectedChange', null, {
value: multiple ? [...(this.state.value as ShorthandCollection), item] : item,
searchQuery: this.getSelectedItemAsString(item),
- }
-
- this.trySetState(newState)
+ })
if (!multiple) {
this.setState({ defaultHighlightedIndex: items.indexOf(item) })
@@ -870,9 +878,6 @@ class Dropdown extends AutoControlledComponent, Dropdo
}
this.tryFocusTriggerButton()
-
- // we don't have event for it, but want to keep the event handling interface, event is empty.
- _.invoke(this.props, 'onSelectedChange', {}, { ...this.props, ...newState })
}
private handleSelectedItemKeyDown(
@@ -896,21 +901,15 @@ class Dropdown extends AutoControlledComponent, Dropdo
break
case previousKey:
if (value.length > 0 && !_.isNil(activeSelectedIndex) && activeSelectedIndex > 0) {
- this.trySetState({
- activeSelectedIndex: activeSelectedIndex - 1,
- })
+ this.trySetState({ activeSelectedIndex: activeSelectedIndex - 1 })
}
break
case nextKey:
if (value.length > 0 && !_.isNil(activeSelectedIndex)) {
if (activeSelectedIndex < value.length - 1) {
- this.trySetState({
- activeSelectedIndex: activeSelectedIndex + 1,
- })
+ this.trySetState({ activeSelectedIndex: activeSelectedIndex + 1 })
} else {
- this.trySetState({
- activeSelectedIndex: null,
- })
+ this.trySetState({ activeSelectedIndex: null })
if (this.props.search) {
e.preventDefault() // prevents caret to forward one position in input.
this.inputRef.current.focus()
@@ -932,9 +931,7 @@ class Dropdown extends AutoControlledComponent, Dropdo
predefinedProps: DropdownSelectedItemProps,
DropdownSelectedItemProps: DropdownSelectedItemProps,
) {
- this.trySetState({
- activeSelectedIndex: null,
- })
+ this.trySetState({ activeSelectedIndex: null })
this.removeItemFromValue(item)
this.tryFocusSearchInput()
this.tryFocusTriggerButton()
@@ -953,14 +950,25 @@ class Dropdown extends AutoControlledComponent, Dropdo
poppedItem = value.pop()
}
- this.trySetState({ value })
-
if (getA11ySelectionMessage && getA11ySelectionMessage.onRemove) {
this.setA11yStatus(getA11ySelectionMessage.onRemove(poppedItem))
}
- // we don't have event for it, but want to keep the event handling interface, event is empty.
- _.invoke(this.props, 'onSelectedChange', {}, { ...this.props, value })
+ this.trySetStateAndInvokeHandler('onSelectedChange', null, { value })
+ }
+
+ /**
+ * Calls trySetState (for autoControlledProps) and invokes event handler exposed to user.
+ * We don't have the event object for most events coming from Downshift se we send an empty event
+ * because we want to keep the event handling interface
+ */
+ private trySetStateAndInvokeHandler = (
+ handlerName: keyof DropdownProps,
+ event: React.SyntheticEvent,
+ newState: Partial,
+ ) => {
+ this.trySetState(newState)
+ _.invoke(this.props, handlerName, event, { ...this.props, ...newState })
}
private tryFocusTriggerButton = () => {
diff --git a/packages/react/src/themes/teams/components/Dropdown/dropdownStyles.ts b/packages/react/src/themes/teams/components/Dropdown/dropdownStyles.ts
index 18d9ca09a9..d6a7c808b4 100644
--- a/packages/react/src/themes/teams/components/Dropdown/dropdownStyles.ts
+++ b/packages/react/src/themes/teams/components/Dropdown/dropdownStyles.ts
@@ -122,7 +122,7 @@ const dropdownStyles: ComponentSlotStylesInput