Skip to content

Commit

Permalink
Add onItemHighlighted prop (#192)
Browse files Browse the repository at this point in the history
* Add onItemHighlighted prop

Useful for updating other parts of the page in reaction to the highlighted item in the autocomplete dropdown being changed

* Revert version bump
  • Loading branch information
SamuelBolduc authored Jun 23, 2020
1 parent c9ceda4 commit 2edfcb7
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ or there is UMD build available. [Check out this pen as example](https://codepen
| boundariesElement | string \| HTMLElement | Element which should prevent autocomplete to overflow. Defaults to _body_. |
| textAreaComponent | React.Component \| {component: React.Component, ref: string} | What component use for as textarea. Default is `textarea`. (You can combine this with [react-autosize-textarea](https://github.com/buildo/react-autosize-textarea) for instance) |
| renderToBody | boolean | When set to `true` the autocomplete will be rendered at the end of the `<body>`. Default is `false`. |
| onItemHighlighted | ({currentTrigger: string \| null, item: string \| Object \| null}) => void | Callback get called everytime item is highlighted in the list |
| onItemSelected | ({currentTrigger: string, item: string \| Object}) => void | Callback get called everytime item is selected |
| style | Style Object | Style's of textarea |
| listStyle | Style Object | Styles of list's wrapper |
Expand Down
14 changes: 13 additions & 1 deletion cypress/integration/textarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,19 @@ describe("React Textarea Autocomplete", () => {
cy.get('[data-test="minChar"]').clear({ force: true });
});

it("onSelectItem should return correct item and trigger", () => {
it("onItemHighlighted should return correct item and trigger", () => {
cy.get(".rta__textarea").type(":ro{uparrow}{uparrow}");
cy.window().then(async win => {
const shouldSelectItem = {
currentTrigger: ":",
item: { name: "rofl", char: "🤣" }
};

expect(win.__lastHighlightedItem).to.deep.equal(shouldSelectItem);
});
});

it("onItemSelected should return correct item and trigger", () => {
cy.get(".rta__textarea").type(":ro{uparrow}{uparrow}{enter}");
cy.window().then(async win => {
const shouldSelectItem = {
Expand Down
4 changes: 4 additions & 0 deletions example/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ class App extends React.Component {
}}
movePopupAsYouType={movePopupAsYouType}
onCaretPositionChange={this._onCaretPositionChangeHandle}
onItemHighlighted={info => {
// save highlighted item to window; use it later in E2E tests
window.__lastHighlightedItem = info;
}}
onItemSelected={info => {
// save selected item to window; use it later in E2E tests
window.__lastSelectedItem = info;
Expand Down
4 changes: 4 additions & 0 deletions src/List.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,13 @@ export default class List extends React.Component<ListProps, ListState> {
};

selectItem = (item: Object | string, keyboard: boolean = false) => {
const { onItemHighlighted } = this.props;

if (this.state.selectedItem === item) return;

this.setState({ selectedItem: item }, () => {
onItemHighlighted(item);

if (keyboard) {
this.props.dropdownScroll(this.itemsRef[this.getId(item)]);
}
Expand Down
23 changes: 21 additions & 2 deletions src/Textarea.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -666,11 +666,14 @@ class ReactTextareaAutocomplete extends React.Component<
* Close autocomplete, also clean up trigger (to avoid slow promises)
*/
_closeAutocomplete = () => {
const { currentTrigger } = this.state;
this.escListenerDestroy();
this.setState({
data: null,
dataLoading: false,
currentTrigger: null
}, () => {
if(currentTrigger) this._onItemHighlightedHandler(null);
});
};

Expand Down Expand Up @@ -703,7 +706,8 @@ class ReactTextareaAutocomplete extends React.Component<
"movePopupAsYouType",
"textAreaComponent",
"renderToBody",
"onItemSelected"
"onItemSelected",
"onItemHighlighted"
];

// eslint-disable-next-line
Expand Down Expand Up @@ -951,6 +955,18 @@ class ReactTextareaAutocomplete extends React.Component<
this._closeAutocomplete();
};

_onItemHighlightedHandler = (item: Object | string | null) => {
const { onItemHighlighted } = this.props;
const { currentTrigger } = this.state;
if(onItemHighlighted) {
if(typeof onItemHighlighted === "function") {
onItemHighlighted({currentTrigger, item});
} else {
throw new Error("`onItemHighlighted` has to be a function");
}
}
}

_dropdownScroll = (item: HTMLDivElement) => {
const { scrollToItem } = this.props;

Expand Down Expand Up @@ -1087,6 +1103,7 @@ class ReactTextareaAutocomplete extends React.Component<
itemClassName={itemClassName}
itemStyle={itemStyle}
getTextToReplace={textToReplace}
onItemHighlighted={this._onItemHighlightedHandler}
onSelect={this._onSelect}
dropdownScroll={this._dropdownScroll}
/>
Expand Down Expand Up @@ -1197,7 +1214,9 @@ ReactTextareaAutocomplete.propTypes = {
dropdownClassName: PropTypes.string,
boundariesElement: containerPropCheck, //eslint-disable-line
trigger: triggerPropsCheck, //eslint-disable-line
renderToBody: PropTypes.bool
renderToBody: PropTypes.bool,
onItemSelected: PropTypes.func,
onItemHighlighted: PropTypes.func,
};

export default ReactTextareaAutocomplete;
2 changes: 2 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export type ListProps = {
itemStyle: ?Object,
className: ?string,
itemClassName: ?string,
onItemHighlighted: (Object | string ) => void,
onSelect: (Object | string) => void,
dropdownScroll: HTMLDivElement => void
};
Expand Down Expand Up @@ -79,6 +80,7 @@ export type TextareaProps = {
| boolean
| ((container: HTMLDivElement, item: HTMLDivElement) => void),
closeOnClickOutside?: boolean,
onItemHighlighted?: ({ currentTrigger: ?string, item: ?Object | ?string }) => void,
onItemSelected?: ({ currentTrigger: string, item: Object | string }) => void,
movePopupAsYouType?: boolean,
boundariesElement: string | HTMLElement,
Expand Down

0 comments on commit 2edfcb7

Please sign in to comment.