Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow user to provide a custom loading indicator #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ The `MentionsInput` supports the following props for configuring the widget:
| suggestionsPortalHost | DOM Element | undefined | Render suggestions into the DOM in the supplied host element. |
| inputRef | React ref | undefined | Accepts a React ref to forward to the underlying input element |
| allowSuggestionsAboveCursor | boolean | false | Renders the SuggestionList above the cursor if there is not enough space below |
| loader | element | null | An element to use as a loading indicator |

Each data source is configured using a `Mention` component, which has the following props:

Expand All @@ -74,9 +75,10 @@ Each data source is configured using a `Mention` component, which has the follow
| renderSuggestion | function (entry, search, highlightedDisplay, index, focused) | `null` | Allows customizing how mention suggestions are rendered (optional) |
| markup | string | `'@[__display__](__id__)'` | A template string for the markup to use for mentions |
| displayTransform | function (id, display) | returns `display` | Accepts a function for customizing the string that is displayed for a mention |
| regex | RegExp | automatically derived from `markup` pattern | Allows providing a custom regular expression for parsing your markup and extracting the placeholder interpolations (optional) | |
| regex | RegExp | automatically derived from `markup` pattern | Allows providing a custom regular expression for parsing your markup and extracting the placeholder interpolations (optional) |
| onAdd | function (id, display) | empty function | Callback invoked when a suggestion has been added (optional) |
| appendSpaceOnAdd | boolean | `false` | Append a space when a suggestion has been added (optional) |
| isLoading | boolean | `false` | Specifies whether the mention suggestions are being loaded. Used to display a loading indicator (optional) |

If a function is passed as the `data` prop, that function will be called with the current search query as first, and a callback function as second argument. The callback can be used to provide results asynchronously, e.g., after fetch requests. (It can even be called multiple times to update the list of suggestions.)

Expand Down
67 changes: 67 additions & 0 deletions demo/src/examples/CustomLoader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { useState } from 'react'
import useStyles from 'substyle'
import { Mention, MentionsInput } from '../../../src'

import { provideExampleValue } from './higher-order'
import defaultStyle from './defaultStyle'
import defaultMentionStyle from './defaultMentionStyle'

const mentionStyle = {
suggestions: {
list: {
border: 'none',
},
},
}

const loaderStyle = {
color: '#d8d8d8',
fontSize: 12,
padding: 6,
}

function CustomLoader({ value, data, onChange }) {
const [isLoading, setIsLoading] = useState(false)

const styles = useStyles(defaultStyle, { style: mentionStyle })

const fetchUsers = (query, callback) => {
if (!query) return

setIsLoading(true)

new Promise((resolve) => {
setTimeout(() => {
resolve(data.filter((user) => user.id.includes(query)))
}, 1500)
}).then((users) => {
setIsLoading(false)
callback(users)
})
}

return (
<div>
<h3>Custom loader component</h3>

<MentionsInput
value={value}
onChange={onChange}
style={styles}
loader={<span style={loaderStyle}>Loading...</span>}
>
<Mention
displayTransform={(login) => `@${login}`}
trigger="@"
data={fetchUsers}
style={defaultMentionStyle}
isLoading={isLoading}
/>
</MentionsInput>
</div>
)
}

const asExample = provideExampleValue('')

export default asExample(CustomLoader)
2 changes: 2 additions & 0 deletions demo/src/examples/Examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import SingleLine from './SingleLine'
import SingleLineIgnoringAccents from './SingleLineIgnoringAccents'
import SuggestionPortal from './SuggestionPortal'
import BottomGuard from './BottomGuard'
import CustomLoader from './CustomLoader'

const users = [
{
Expand Down Expand Up @@ -63,6 +64,7 @@ export default function Examples() {
<Emojis data={users} />
<SuggestionPortal data={users} />
<BottomGuard data={users} />
<CustomLoader data={users} />
</div>
</StylesViaJss>
)
Expand Down
3 changes: 3 additions & 0 deletions src/MentionsInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const propTypes = {
allowSpaceInQuery: PropTypes.bool,
allowSuggestionsAboveCursor: PropTypes.bool,
ignoreAccents: PropTypes.bool,
loader: PropTypes.element,

value: PropTypes.string,
onKeyDown: PropTypes.func,
Expand Down Expand Up @@ -105,6 +106,7 @@ class MentionsInput extends React.Component {
ignoreAccents: false,
singleLine: false,
allowSuggestionsAboveCursor: false,
loader: null,
onKeyDown: () => null,
onSelect: () => null,
onBlur: () => null,
Expand Down Expand Up @@ -260,6 +262,7 @@ class MentionsInput extends React.Component {
onMouseDown={this.handleSuggestionsMouseDown}
onMouseEnter={this.handleSuggestionsMouseEnter}
isLoading={this.isLoading()}
loader={this.props.loader}
ignoreAccents={this.props.ignoreAccents}
>
{this.props.children}
Expand Down
7 changes: 6 additions & 1 deletion src/SuggestionsOverlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class SuggestionsOverlay extends Component {
top: PropTypes.number,
scrollFocusedIntoView: PropTypes.bool,
isLoading: PropTypes.bool,
loader: PropTypes.element,
onSelect: PropTypes.func,
ignoreAccents: PropTypes.bool,
containerRef: PropTypes.oneOfType([
Expand Down Expand Up @@ -138,7 +139,11 @@ class SuggestionsOverlay extends Component {
return
}

return <LoadingIndicator style={this.props.style('loadingIndicator')} />
return (
this.props.loader || (
<LoadingIndicator style={this.props.style('loadingIndicator')} />
)
)
}

handleMouseEnter = (index, ev) => {
Expand Down