Skip to content

Commit

Permalink
feat(filterable-multiselect): add onMenuChange event (#7370)
Browse files Browse the repository at this point in the history
* feat(filterable-multiselect): add onMenuChange event

* feat(filterable-multiselect): fix onMenuChange event

* Update packages/react/src/components/MultiSelect/FilterableMultiSelect.js

Co-authored-by: emyarod <[email protected]>

Co-authored-by: emyarod <[email protected]>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 4, 2020
1 parent 73a73c7 commit 27ce461
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 83 deletions.
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,15 @@
"contributions": [
"code"
]
},
{
"login": "munkurious",
"name": "Boston Cartwright",
"avatar_url": "https://avatars0.githubusercontent.com/u/2187109?v=4",
"profile": "https://github.com/munkurious",
"contributions": [
"code"
]
}
],
"commitConvention": "none"
Expand Down
127 changes: 64 additions & 63 deletions README.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3576,6 +3576,9 @@ Map {
"onChange": Object {
"type": "func",
},
"onMenuChange": Object {
"type": "func",
},
"open": Object {
"type": "bool",
},
Expand Down
48 changes: 28 additions & 20 deletions packages/react/src/components/MultiSelect/FilterableMultiSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ export default class FilterableMultiSelect extends React.Component {
*/
onChange: PropTypes.func,

/**
* `onMenuChange` is a utility for this controlled component to communicate to a
* consuming component that the menu was opened(`true`)/closed(`false`).
*/
onMenuChange: PropTypes.func,

/**
* Initialize the component with an open(`true`)/closed(`false`) menu.
*/
Expand Down Expand Up @@ -184,15 +190,17 @@ export default class FilterableMultiSelect extends React.Component {
}
};

handleOnToggleMenu = () => {
handleOnMenuChange = (isOpen) => {
this.setState((state) => ({
isOpen: !state.isOpen,
isOpen: isOpen ?? !state.isOpen,
}));
if (this.props.onMenuChange) {
this.props.onMenuChange(isOpen);
}
};

handleOnOuterClick = () => {
this.setState({
isOpen: false,
inputValue: '',
});
};
Expand All @@ -211,32 +219,30 @@ export default class FilterableMultiSelect extends React.Component {
case Downshift.stateChangeTypes.keyDownArrowDown:
this.setState({
highlightedIndex: changes.highlightedIndex,
isOpen: true,
});
if (!this.state.isOpen) this.handleOnMenuChange(true);
break;
case Downshift.stateChangeTypes.keyDownEscape:
case Downshift.stateChangeTypes.mouseUp:
this.setState({ isOpen: false });
if (this.state.isOpen) this.handleOnMenuChange(false);
break;
// Opt-in to some cases where we should be toggling the menu based on
// a given key press or mouse handler
// Reference: https://github.com/paypal/downshift/issues/206
case Downshift.stateChangeTypes.clickButton:
case Downshift.stateChangeTypes.keyDownSpaceButton:
this.setState(() => {
let nextIsOpen = changes.isOpen || false;
if (changes.isOpen === false) {
// If Downshift is trying to close the menu, but we know the input
// is the active element in thedocument, then keep the menu open
if (this.inputNode === document.activeElement) {
nextIsOpen = true;
}
case Downshift.stateChangeTypes.keyDownSpaceButton: {
let nextIsOpen = changes.isOpen || false;
if (changes.isOpen === false) {
// If Downshift is trying to close the menu, but we know the input
// is the active element in the document, then keep the menu open
if (this.inputNode === document.activeElement) {
nextIsOpen = true;
}
return {
isOpen: nextIsOpen,
};
});
}
if (this.state.isOpen !== nextIsOpen)
this.handleOnMenuChange(nextIsOpen);
break;
}
}
};

Expand All @@ -245,7 +251,7 @@ export default class FilterableMultiSelect extends React.Component {
};

handleOnInputValueChange = (inputValue, { type }) => {
if (type === Downshift.stateChangeTypes.changeInput)
if (type === Downshift.stateChangeTypes.changeInput) {
this.setState(() => {
if (Array.isArray(inputValue)) {
return {
Expand All @@ -254,9 +260,11 @@ export default class FilterableMultiSelect extends React.Component {
}
return {
inputValue: inputValue || '',
isOpen: Boolean(inputValue) || this.state.isOpen,
};
});
if (Boolean(inputValue) !== this.state.isOpen)
this.handleOnMenuChange(Boolean(inputValue));
}
};

clearInputValue = (event) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ export const _Filterable = withReadme(readme, () => {
placeholder={defaultPlaceholder}
translateWithId={(id) => listBoxMenuIconTranslationIds[id]}
selectionFeedback={selectionFeedback}
onMenuChange={(e) => {
multiSelectProps.onMenuChange(e);
}}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe('MultiSelect.Filterable', () => {
items: generateItems(5, generateGenericItem),
initialSelectedItems: [],
onChange: jest.fn(),
onMenuChange: jest.fn(),
placeholder: 'Placeholder...',
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ exports[`MultiSelect.Filterable should render 1`] = `
light={false}
locale="en"
onChange={[MockFunction]}
onMenuChange={[MockFunction]}
open={false}
placeholder="Placeholder..."
selectionFeedback="top-after-reopen"
Expand Down

0 comments on commit 27ce461

Please sign in to comment.