JSFiddle - React, Tailwind, and code Playground

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Auto-complete</title>
  <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300&display=swap" rel="stylesheet">
  <style>
    * {
      font-family: 'Open Sans', sans-serif;
    }

    body {
      display: flex;
      justify-content: center;
      align-items: center;
    }

    h1 {
      text-align: center;
      position: absolute;
      margin-top: 10%;
      letter-spacing: 1px;
      margin-left: 20px;
      font-weight: 300;
    }

    #input {
        background: transparent;
        outline: none;
        border: 1px solid grey;
        z-index: 10;
        width: 582px;
        height: 44px;
        font-size: 25px;
        border-radius: 20px;
        padding-left: 20px;
        padding-top: 10px;
        margin-top: 35%;
    }

    .div {
        width: auto;
        display: inline-block;
        visibility: hidden;
        position: fixed;
        overflow: auto;
        font-size: 25px;
    }

    #time {
      font-style: italic;
      font-size: 13px;
      margin-left: 20px;
      text-decoration: underline;
      letter-spacing: 0.5px;
    }
  </style>
</head>
<body>
<div>
  <h1>Auto-complete...</h1>
  <div contenteditable="true" id="input"></div>
  <div id="time"></div>
  <div id='fake-div' class='div'></div>

  <script src="index.js"></script>
</div>
</body>
</html>

JavaScript

const $input = document.getElementById('input');
const $time = document.getElementById('time');
const $fakeDiv = document.getElementById('fake-div');
const r = $input.getBoundingClientRect();
let INPUT_DEBOUNCE = null;

const $span = document.createElement('span');

const css = getComputedStyle($input);

$span.style.cssText = `
    width: ${r.width}px;
    height: ${r.height}px;
    left: ${r.left}px;
    top: ${r.top}px;
    z-index: -10;
    opacity: 0.4;
    position: absolute;
    white-space: pre-wrap;
    font-size: ${parseInt(css.fontSize)}px;
    padding-left: ${parseInt(css.paddingLeft)}px;
    padding-top: ${parseInt(css.paddingTop) + 1}px;
`;

document.body.appendChild($span);

class Trie {
  constructor() {
    this.trie = null;
    this.suggestions = [];
  }

  newNode() {
    return {
      isLeaf: false,
      children: {}
    }
  }

  add(word) {
    if (!this.trie) this.trie = this.newNode();

    let root = this.trie;
    for (const letter of word) {
      if (!(letter in root.children)) {
        root.children[letter] = this.newNode();
      }
      root = root.children[letter];
    }
    root.isLeaf = true;
  }

  find(word) {
    let root = this.trie;
    for (const letter of word) {
      if (letter in root.children) {
        root = root.children[letter];
      } else {
        return null;
      }
    }

    return root;
  }

  traverse(root, word) {
    if (root.isLeaf) {
      this.suggestions.push(word);
      return;
    }

    for (const letter in root.children) {
      this.traverse(root.children[letter], word + letter);
    }
  }

  complete(word, CHILDREN = null) {
    const root = this.find(word);

    if (!root) return this.suggestions; // cannot suggest anything

    const children = root.children;

    let spread = 0;

    for (const letter in children) {
      this.traverse(children[letter], word + letter);
      spread++;

      if (CHILDREN && spread === CHILDREN) break;
    }

    return this.suggestions;
  }

  clear() {
 ...