For rich text, I would just use ProseMirror or Lexical and avoid the pain of working with contenteditable directly.
To appreciate the difficulty and nuances with building a text editor on contenteditable, I would read through the commit history on ProseMirror https://github.com/ProseMirror/prosemirror-view/commits/mast...