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

feat: Add onBeforeStart and onBeforeUpdate handlers to the render function #2628

Merged
merged 1 commit into from Apr 28, 2022

Conversation

rfgamaral
Copy link
Contributor

@rfgamaral rfgamaral commented Mar 17, 2022

This simple change provides onBefore* handlers to the render function, allowing one to start rendering a loading spinner, for instance, while waiting for async items to be received from a backend service.

A working demo can be found here:


With this change, the meaning of each handler now becomes:

  • onBeforeStart: Invoked once as soon as the user types the suggestion trigger character
    • Async: This is where a dropdown would be first rendered with a loading spinner
    • Not-async: There's no use for this handler in this situation (can be omitted)
  • onStart: Invoked once as soon as the first results from the async call are received
    • Async: This is where a dropdown would be updated with the first results (replacing the loading spinner)
    • Not-async: This is where a dropdown would be first rendered with the first results
  • onBeforeUpdate: Invoked every time for each character pressed, and as soon as it's pressed
    • Async: This is where a dropdown would be updated with a loading spinner
    • Not-async: There's no use for this handler in this situation (can be omitted)
  • onUpdate: Invoked every time for each character pressed, and as soon as the filtered results from the async call are received
    • Async: This is where a dropdown would be updated with the filtered results (replacing the loading spinner)
    • Not-async: This is where a dropdown would be rendered again with the filtered results

Here's how a render function could look like (unoptimized code, some duplication can probably be avoided):

render: () => {
    let reactRenderer
    let dropdown

    return {
        onBeforeStart: (props) => {
            reactRenderer = new ReactRenderer(MentionList, {
                props: {
                    ...props,
                    items: null, // represents loading state
                },
                editor: props.editor,
            })

            if (props.decorationNode) {
                dropdown = tippy(props.decorationNode, {
                    getReferenceClientRect: props.clientRect,
                    appendTo: () => document.body,
                    content: reactRenderer.element,
                    duration: [150, 200],
                    interactive: true,
                    placement: 'bottom-start',
                    showOnCreate: true,
                    trigger: 'manual',
                })
            }
        },
        onStart(props) {
            reactRenderer.updateProps(props)

            dropdown.setProps({
                getReferenceClientRect: props.clientRect,
            })
        },
        onBeforeUpdate(props) {
            reactRenderer.updateProps({
                ...props,
                items: null, // represents loading state
            })

            dropdown.setProps({
                getReferenceClientRect: props.clientRect,
            })
        },
        onUpdate(props) {
            reactRenderer.updateProps(props)

            dropdown.setProps({
                getReferenceClientRect: props.clientRect,
            })
        },
        onKeyDown(props) {
            if (props.event.key === 'Escape') {
                dropdown.hide()
                return true
            }

            return Boolean(reactRenderer.ref?.onKeyDown(props))
        },
        onExit() {
            dropdown.destroy()
            reactRenderer.destroy()
        },
    }
}

@netlify
Copy link

netlify bot commented Mar 17, 2022

Deploy Preview for tiptap-embed ready!

Name Link
🔨 Latest commit 9c5f8f5
🔍 Latest deploy log https://app.netlify.com/sites/tiptap-embed/deploys/626a62dc5e2287000997e0cf
😎 Deploy Preview https://deploy-preview-2628--tiptap-embed.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@rfgamaral
Copy link
Contributor Author

@bdbch Any thoughts on this PR? Do you think this is something that you could merge?

@bdbch bdbch self-requested a review April 28, 2022 00:45
@bdbch bdbch self-assigned this Apr 28, 2022
@bdbch
Copy link
Contributor

bdbch commented Apr 28, 2022

Thanks for your PR @rfgamaral
Could you maybe merge the current main into your PR so the test checks run through?

@bdbch bdbch merged commit 70cb809 into ueberdosis:main Apr 28, 2022
@rfgamaral rfgamaral deleted the suggestion-async-renderer branch April 28, 2022 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants