ianstormtaylor / slate

A completely customizable framework for building rich text editors. (Currently in beta.)
http://slatejs.org
MIT License
29.71k stars 3.24k forks source link

[Safari] RichText issues when deleting all text with markup, including deleting the placeholder #4640

Open Belline opened 2 years ago

Belline commented 2 years ago

Description On Safari, when deleting all content from a textarea that has richtext markup, after all content is removed, the user is able to also delete the placeholder, and after that it keeps throwing an error and it doesn't allow the user to edit the editor again without having to refresh the whole page.

Recording

https://user-images.githubusercontent.com/8379566/139514128-d331a9c4-0b2c-4f2f-b0e6-eaff211e5d9f.mov

Sandbox https://www.slatejs.org/examples/richtext https://deploy-preview-4627--slatejs.netlify.app/examples/richtext

Steps To reproduce the behavior:

  1. Go to any editor with RichText and placeholder on Safari (like the richtext example page)
  2. Type any text
  3. Add a markup to that text (bold, italic, etc)
  4. Delete all text
  5. Hit backspace again, it will delete the whole placeholder
  6. You won't be able to use that editor again without refreshing

Expectation The user shouldn't be able to delete the placeholder if the text has markup, it should behave as if the text doesn't have a markup, also, no error should be thrown and the editor must be editable and work fine even after I delete all text on Safari

Environment

Context It only happens on Safari, Chrome and Firefox works fine. It's probably related with #4611 but it doesn't got fixed by the PR #4627 (this bug also happens on https://deploy-preview-4627--slatejs.netlify.app/examples/richtext)

Belline commented 2 years ago

for anyone experiencing this issue, I've developed a workaround that is working well on our app and prevents the issue from happening, although it's still a workaround for an issue that is still there.

The idea is to create a custom plugin that will handle onKeyDown and prevent backspackes from happening by preventing the html element from firing the event to Slate. (WithOverride and editor.deleteBackward event won't work here when there's only the placeholder element)

// pseudo-code, untested
const withPreventPlaceholderDeletion = editor => {
  editor.onKeyDown = event => {
    // in case editor.isEmpty() is not working as it should for your use case
    // you might want to check the children using a custom fn
    const customEditorIsEmpty = () => { // no-op };
    const isEditorEmpty = editor.isEmpty() || customEditorIsEmpty();
    if (event.key === 'Backspace' && editor.isEmpty()) {
      event.preventDefault();
    }
  }
  return editor
}