title: Can't get caret position with window.getSelection() on Safari
body: <p>I'm working with React <code>v17</code> and <code>emoji-mart: ^3.0.1</code>.</p>
  <ul>
  <li><p>I can pick the emojis and log it out but it fails when trying to insert/display the emojis in the <code>ContentEditable</code> component.</p>
  </li>
  <li><p>The Emojis that got picked are <strong>displayed normally on Chrome</strong> but don't display anything at all on <strong>Safari</strong> - both mobile and desktop.</p>
  </li>
  <li><p>It seems like window.getSelection() method doesn't work on Safari, so the <code>saveCaretPosition</code> function doesn't work. That's why the <code>insertEmoji</code> function couldn't add the Emoji in the <code>Editor</code>.</p>
  </li>
  </ul>
  <p>-&gt; Is there any workaround of <code>window.getSelection()</code> for Safari?</p>
  <hr />
  <h3>Issue was found on:</h3>
  <ul>
  <li>macOS Big Sur 11.4: Safari (Version 14.1.1)</li>
  <li>iPad iOS 13.1.3: Safari</li>
  </ul>
  <hr />
  <h3>Demo + Screenshots:</h3>
  <ol>
  <li>Chrome + console</li>
  </ol>
  <img src="https://i.stack.imgur.com/NPnhy.gif" width="400" alt="chrome" />
  <img src="https://i.stack.imgur.com/pXRpi.png" width="400" alt="chrome console" />
  <ol start="2">
  <li>Safari + console</li>
  </ol>
  <img src="https://i.stack.imgur.com/oRvCD.gif" width="400" alt="safari" />
  <img src="https://i.stack.imgur.com/7ZHY6.png" width="400" alt="safari console" />
  <hr />
  <h3>The code:</h3>
  <p><strong>EmojiPicker.tsx</strong></p>
  <pre><code>  const EmojiPicker = ({ onSelectEmoji }: Props) =&gt; {
     const control = useVisibilityControl()
  
     const handleClickOnEmoji = (emoji: BaseEmoji) =&gt; {
       control.hide()
       onSelectEmoji(emoji)
       console.log(emoji) // -&gt; Logs the payload successfully!
     }
  
    return (
      &lt;div className='editor__header'&gt;
        &lt;Popover
          control={control}
          position='absolute'
          className='z-5'
          trigger={
            &lt;div&gt;
              &lt;Icon
                name='emoji-button'
                size={23}
              /&gt;
            &lt;/div&gt;
          }
          placement={'bottom-right'}
          disableScrollOnVisible&gt;
          &lt;Picker
            onClick={handleClickOnEmoji}
            showSkinTones={false}
            color='#F1B700'
            showPreview={false}
          /&gt;
        &lt;/Popover&gt;
      &lt;/div&gt;
    )}
  </code></pre>
  <p><strong>RangeUtils.ts</strong></p>
  <pre><code>const getCaretPosition = () =&gt; {
    if (window.getSelection) {
      const sel = window.getSelection()
      if (sel.getRangeAt &amp;&amp; sel.rangeCount) {
        return sel.getRangeAt(0)
      }
    }
    return null
  }
  </code></pre>
  <p><strong>Editor.tsx</strong></p>
  <pre><code>let savedRange: Range
  
  const Editor = ({ placeholders }: Props) =&gt; {
  
    const editorRef = useRef(null)
    const tributeRef = useRef&lt;Tribute&lt;TemplatePlaceholder&gt;&gt;()
  
  
    useEffect(() =&gt; {
      const editorElm = editorRef.current
      if (!editorElm) return undefined
  
      if (placeholders &amp;&amp; !tributeRef.current) {
        initTribute(editorElm)
      }
  
      return () =&gt; {
        if (tributeRef.current) {
          tributeRef.current.detach(editorElm)
          tributeRef.current = null
        }
      }
    }, [placeholders, initTribute])
  
   
    const saveCaretPosition = () =&gt; {
      savedRange = RangeUtils.getCaretPosition()
    }
  
    const insertEmoji = (emoji: BaseEmoji) =&gt; {
      console.log(isValidCaret()) // -&gt; Logs 'undefined' on Safari, 'true' on Chrome
      if (!isValidCaret()) {
        console.log('bugsssss') // -&gt; Error only caught on Safari
        return
      }
      
      console.log('emoji selected successfully')
      RangeUtils.restoreCaretPosition(savedRange)
      setTimeout(() =&gt; {
        savedRange = RangeUtils.insertTextAtCaret(savedRange, emoji.native)
        onChange(editorRef.current.innerHTML)
      }, 0)
    }
  
    const isValidCaret = () =&gt; {
      const startContainer = savedRange?.startContainer as HTMLElement
      return startContainer?.isContentEditable || startContainer?.parentElement?.isContentEditable
    }
  
    return (
      &lt;&gt;
        &lt;div className='editor__wrapper editor'&gt;
        
          &lt;EmojiPicker onSelectEmoji={insertEmoji} /&gt;
  
          &lt;div className='editor__content'&gt;
            &lt;ContentEditable
              innerRef={editorRef}
              html={value || ''}
              onKeyDown={event =&gt; {
                if (event.key === 'Enter') {
                  document.execCommand('insertLineBreak')
                  event.preventDefault()
                }
              }}
              onChange={(event: ContentEditableEvent) =&gt; {
                onChange(event.target.value)
              }}
              onBlur={() =&gt; {
                saveCaretPosition()
                onBlur()
              }}
              onPaste={handlePaste}
              spellCheck={false}
            /&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/&gt;
    )
  }
  </code></pre>