Search

Nonlinear Scale Mode

Time and Scales

Space events evenly to make the sequences easier to see.

Nonlinear Scale Mode
View live example →

Use the checkbox under the timeline to view the events in nonlinear scale mode. Hover to see a tooltip with the true time of the events.

See Also

import { createTimeline } from "kronograph";
import data from "./data";

const toggleCheckbox = document.getElementById("toggle-scalemode");
const tooltip = document.getElementById("tooltip");
const tooltipTimestamp = document.getElementById("tooltip-timestamp");

let isNonlinear = false;

function getEventTime(event) {
  let time = event.time;
  if (time.start) {
    time = time.start;
  }
  return typeof time !== "number" ? time.getTime() : time;
}

function hideTooltip() {
  tooltip.style.display = "none";
}

function showTooltip(eventIds, x, y) {
  const eventTime = getEventTime(data.events[eventIds[0]]);
  tooltipTimestamp.innerText = new Date(eventTime).toLocaleString("en-US", { timeZone: "UTC" });
  tooltip.style.display = "flex";
  tooltip.style.left = `${x}px`;
  tooltip.style.top = `${y}px`;
}

const timeline = createTimeline({
  container: "my-timeline",
});

function setSpacing(checked) {
  isNonlinear = checked;
  const scaleMode = checked ? "nonlinear" : "linear";
  timeline.options({ scales: { scaleMode } });
}

toggleCheckbox.addEventListener("change", () => setSpacing(toggleCheckbox.checked));
timeline.on("pointer-move", ({ eventIds, targetType, x, y }) => {
  if (!isNonlinear) {
    return;
  }

  if (targetType === "event" || targetType === "eventSummary") {
    showTooltip(eventIds, x, y);
  } else {
    hideTooltip();
  }
});

timeline.set(data);
timeline.fit();
export default {
  entities: {
    target0: {
      label: "GFHeX DeFi",
      type: "target",
    },
    target1: {
      type: "target",
      label: "Cryptomonium",
    },
    target2: {
      label: "CoinCoffer",
      type: "target",
    },
    "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86": {
      type: "bad",
      label: "0x1b6...caa86",
      data: {
        addr: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
    },
    "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1": {
      type: "bad",
      label: "0x8cf...bdce1",
      data: {
        addr: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
    },
    "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d": {
      type: "bad",
      label: "0x8e9...bd27d",
      data: {
        addr: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
    },
    "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942": {
      type: "good",
      label: "0xb9b...0d942",
      data: {
        addr: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
      },
    },
    "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a": {
      type: "good",
      label: "0xca3...9bf9a",
      data: {
        addr: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
    },
    "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7": {
      type: "good",
      label: "0xfcb...0cea7",
      data: {
        addr: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
      },
    },
    "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6": {
      type: "good",
      label: "0x9b7...c20b6",
      data: {
        addr: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
    },
    "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773": {
      type: "good",
      label: "0x5a2...d4773",
      data: {
        addr: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
      },
    },
    "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb": {
      type: "good",
      label: "0xe26...e7cbb",
      data: {
        addr: "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb",
      },
    },
    "0xf3fe6cfa8fe228efaa14e54db2b024b2f5cc8bea": {
      type: "good",
      label: "0xf3f...c8bea",
      data: {
        addr: "0xf3fe6cfa8fe228efaa14e54db2b024b2f5cc8bea",
      },
    },
    "0x84d29f34ce7b2c0ead2ff21d0c15b6f7c0ba55be": {
      type: "good",
      label: "0x84d...a55be",
      data: {
        addr: "0x84d29f34ce7b2c0ead2ff21d0c15b6f7c0ba55be",
      },
    },
    "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d": {
      type: "good",
      label: "0xb96...dbc0d",
      data: {
        addr: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
      },
    },
    "0xceea8c671edfe9ede809de00fdaad9abd9a4db00": {
      type: "good",
      label: "0xcee...4db00",
      data: {
        addr: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
      },
    },
    "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced": {
      type: "good",
      label: "0xebc...15ced",
      data: {
        addr: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
      },
    },
    "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f": {
      type: "good",
      label: "0xdfa...fba7f",
      data: {
        addr: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
      },
    },
  },
  events: {
    "hack-0": {
      time: 1579415511083,
      entityIds: ["target0", "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86"],
    },
    "hack-1": {
      time: 1579540934827,
      entityIds: ["target1", "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1"],
    },
    "hack-2": {
      time: 1579616069208,
      entityIds: ["target2", "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d"],
    },
    b0: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579578052573,
    },
    b1: {
      entityIds: {
        to: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579717135123,
    },
    b2: {
      entityIds: {
        to: "0xf3fe6cfa8fe228efaa14e54db2b024b2f5cc8bea",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580424438316,
    },
    b3: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580260774220,
    },
    b4: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580317033641,
    },
    b5: {
      entityIds: {
        to: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579964887255,
    },
    b6: {
      entityIds: {
        to: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580070729345,
    },
    b7: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579685968108,
    },
    b8: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579811564040,
    },
    b9: {
      entityIds: {
        to: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579459998748,
    },
    b10: {
      entityIds: {
        to: "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580208104888,
    },
    b11: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579745745176,
    },
    b12: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580058489146,
    },
    b13: {
      entityIds: {
        to: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579717347316,
    },
    b14: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579494494439,
    },
    b15: {
      entityIds: {
        to: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579885644155,
    },
    b16: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580200466161,
    },
    b17: {
      entityIds: {
        to: "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580114388612,
    },
    b18: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580151351355,
    },
    b19: {
      entityIds: {
        to: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579445850906,
    },
    b20: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580254979723,
    },
    b21: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1580382557651,
    },
    b22: {
      entityIds: {
        to: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580120152113,
    },
    b23: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579775308805,
    },
    b24: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579795163788,
    },
    b25: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580369808460,
    },
    b26: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580344329765,
    },
    b27: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579854724787,
    },
    b28: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579558600372,
    },
    b29: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579508324590,
    },
    b30: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1580118604982,
    },
    b31: {
      entityIds: {
        to: "0xf3fe6cfa8fe228efaa14e54db2b024b2f5cc8bea",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580041273248,
    },
    b32: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579652671402,
    },
    b33: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579885382816,
    },
    b34: {
      entityIds: {
        to: "0x84d29f34ce7b2c0ead2ff21d0c15b6f7c0ba55be",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580094866632,
    },
    b35: {
      entityIds: {
        to: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579648956755,
    },
    b36: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580424827352,
    },
    b37: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1580007474826,
    },
    b38: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579884032025,
    },
    b39: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1580322435082,
    },
    r0: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
      },
      time: 1628683178752,
    },
    r1: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1627730030640,
    },
    r2: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
      time: 1626649248873,
    },
    r3: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
      time: 1627414620701,
    },
    r4: {
      entityIds: {
        to: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
        from: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
      time: 1627767070935,
    },
    r5: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
      time: 1626193705239,
    },
    r6: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
      time: 1626288390335,
    },
    r7: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
      },
      time: 1628570278211,
    },
    r8: {
      entityIds: {
        to: "0x84d29f34ce7b2c0ead2ff21d0c15b6f7c0ba55be",
        from: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
      },
      time: 1628102690120,
    },
    r9: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb",
      },
      time: 1627805727668,
    },
    r10: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
      time: 1628129790779,
    },
    r11: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
      time: 1625794960150,
    },
    r12: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
      },
      time: 1626945105626,
    },
    r13: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
      },
      time: 1627415639668,
    },
    r14: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
      },
      time: 1627204207491,
    },
    r15: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
      },
      time: 1627112157932,
    },
    r16: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
      },
      time: 1628543246465,
    },
    r17: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1627474448769,
    },
    r18: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
      },
      time: 1627824827313,
    },
    r19: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
      time: 1628883517321,
    },
  },
  entityTypes: {
    good: {
      typeLabel: "Other Addresses",
      color: "#2E86C1",
      typeGlyph: true,
      order: 2,
    },
    bad: {
      typeLabel: "Suspicious Addresses",
      color: "#CB4335",
      typeGlyph: true,
      order: 1,
    },
    target: {
      typeLabel: "Hack Targets",
      color: "#28B463",
      typeGlyph: true,
      order: 0,
    },
  },
};
<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="@ci/theme/kg/css/examples.css" />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div class="story">
      <div id="tooltip">
        <div id="tooltip-arrow"></div>
        <span id="tooltip-timestamp"></span>
      </div>
      <div class="story__timeline" id="my-timeline"></div>
      <div class="story__controls story__controls--row">
        <div
          class="story__controls__button-container story__controls__item__checkbox-and-label-container"
        >
          <label for="toggle-scalemode">Nonlinear Scale Mode</label>
          <input id="toggle-scalemode" type="checkbox" name="scale-mode" />
        </div>
      </div>
    </div>
    <script type="module" src="./code.js"></script>
  </body>
</html>
#tooltip > span {
  background-color: #3d4852;
  padding: 2.5px 5px;
  border-radius: 5px;
}

#tooltip {
  display: none;
  align-items: center;
  position: absolute;
  transform: translate(0, -50%);
  transform-origin: left center;
  pointer-events: none;
  z-index: 10;
  white-space: nowrap;
}

#tooltip-arrow {
  width: 0;
  height: 0;
  border-top: 10px solid transparent;
  border-bottom: 10px solid transparent;
  border-right: 10px solid #3d4852;
}
import React from "react";
import { createRoot } from "react-dom/client";
import Timeline from "kronograph/react/Timeline";
import data from "./data";

export const Demo = () => {
  const [options, setOptions] = React.useState({});
  const [tooltip, setTooltip] = React.useState(null);
  const [nonLinearSpacing, setNonLinearSpacing] = React.useState(false);
  const timelineRef = React.useRef();

  function setScaleMode(checked) {
    const scaleMode = checked ? "nonlinear" : "linear";
    setOptions({
      scales: {
        scaleMode,
      },
    });
    setNonLinearSpacing(checked);
  }

  function handlePointerMove({ targetType, eventIds, x, y }) {
    if (nonLinearSpacing === false) {
      return;
    }

    setTooltip(
      targetType === "event" || targetType === "eventSummary"
        ? {
            eventIds,
            x,
            y,
          }
        : null
    );
  }

  return (
    <div className="story">
      <div
        id="tooltip"
        style={{
          display: tooltip === null ? "none" : "flex",
          left: tooltip === null ? 0 : `${tooltip.x}px`,
          top: tooltip === null ? 0 : `${tooltip.y}px`,
        }}
      >
        <div id="tooltip-arrow"></div>
        <span id="tooltip-timestamp">
          {tooltip === null
            ? ""
            : new Date(data.events[tooltip.eventIds[0]].time).toLocaleString("en-US", {
                timeZone: "UTC",
              })}
        </span>
      </div>
      <Timeline
        entities={data.entities}
        events={data.events}
        entityTypes={data.entityTypes}
        options={options}
        ref={timelineRef}
        onTimelinePointerMove={handlePointerMove}
      />
      <div className="story__controls story__controls--row">
        <div className="story__controls__button-container story__controls__item__checkbox-and-label-container">
          <label htmlFor="toggle-scalemode">Nonlinear Scale Mode</label>
          <input
            id="toggle-scalemode"
            type="checkbox"
            name="scale-mode"
            onChange={(event) => {
              setScaleMode(event.target.checked);
            }}
          />
        </div>
      </div>
    </div>
  );
};

const root = createRoot(document.getElementById("my-timeline"));
root.render(<Demo />);
export default {
  entities: {
    target0: {
      label: "GFHeX DeFi",
      type: "target",
    },
    target1: {
      type: "target",
      label: "Cryptomonium",
    },
    target2: {
      label: "CoinCoffer",
      type: "target",
    },
    "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86": {
      type: "bad",
      label: "0x1b6...caa86",
      data: {
        addr: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
    },
    "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1": {
      type: "bad",
      label: "0x8cf...bdce1",
      data: {
        addr: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
    },
    "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d": {
      type: "bad",
      label: "0x8e9...bd27d",
      data: {
        addr: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
    },
    "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942": {
      type: "good",
      label: "0xb9b...0d942",
      data: {
        addr: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
      },
    },
    "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a": {
      type: "good",
      label: "0xca3...9bf9a",
      data: {
        addr: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
    },
    "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7": {
      type: "good",
      label: "0xfcb...0cea7",
      data: {
        addr: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
      },
    },
    "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6": {
      type: "good",
      label: "0x9b7...c20b6",
      data: {
        addr: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
    },
    "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773": {
      type: "good",
      label: "0x5a2...d4773",
      data: {
        addr: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
      },
    },
    "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb": {
      type: "good",
      label: "0xe26...e7cbb",
      data: {
        addr: "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb",
      },
    },
    "0xf3fe6cfa8fe228efaa14e54db2b024b2f5cc8bea": {
      type: "good",
      label: "0xf3f...c8bea",
      data: {
        addr: "0xf3fe6cfa8fe228efaa14e54db2b024b2f5cc8bea",
      },
    },
    "0x84d29f34ce7b2c0ead2ff21d0c15b6f7c0ba55be": {
      type: "good",
      label: "0x84d...a55be",
      data: {
        addr: "0x84d29f34ce7b2c0ead2ff21d0c15b6f7c0ba55be",
      },
    },
    "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d": {
      type: "good",
      label: "0xb96...dbc0d",
      data: {
        addr: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
      },
    },
    "0xceea8c671edfe9ede809de00fdaad9abd9a4db00": {
      type: "good",
      label: "0xcee...4db00",
      data: {
        addr: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
      },
    },
    "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced": {
      type: "good",
      label: "0xebc...15ced",
      data: {
        addr: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
      },
    },
    "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f": {
      type: "good",
      label: "0xdfa...fba7f",
      data: {
        addr: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
      },
    },
  },
  events: {
    "hack-0": {
      time: 1579415511083,
      entityIds: ["target0", "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86"],
    },
    "hack-1": {
      time: 1579540934827,
      entityIds: ["target1", "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1"],
    },
    "hack-2": {
      time: 1579616069208,
      entityIds: ["target2", "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d"],
    },
    b0: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579578052573,
    },
    b1: {
      entityIds: {
        to: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579717135123,
    },
    b2: {
      entityIds: {
        to: "0xf3fe6cfa8fe228efaa14e54db2b024b2f5cc8bea",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580424438316,
    },
    b3: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580260774220,
    },
    b4: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580317033641,
    },
    b5: {
      entityIds: {
        to: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579964887255,
    },
    b6: {
      entityIds: {
        to: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580070729345,
    },
    b7: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579685968108,
    },
    b8: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579811564040,
    },
    b9: {
      entityIds: {
        to: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579459998748,
    },
    b10: {
      entityIds: {
        to: "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580208104888,
    },
    b11: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579745745176,
    },
    b12: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580058489146,
    },
    b13: {
      entityIds: {
        to: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579717347316,
    },
    b14: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579494494439,
    },
    b15: {
      entityIds: {
        to: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579885644155,
    },
    b16: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580200466161,
    },
    b17: {
      entityIds: {
        to: "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580114388612,
    },
    b18: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580151351355,
    },
    b19: {
      entityIds: {
        to: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579445850906,
    },
    b20: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580254979723,
    },
    b21: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1580382557651,
    },
    b22: {
      entityIds: {
        to: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580120152113,
    },
    b23: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579775308805,
    },
    b24: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579795163788,
    },
    b25: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1580369808460,
    },
    b26: {
      entityIds: {
        to: "0xceea8c671edfe9ede809de00fdaad9abd9a4db00",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580344329765,
    },
    b27: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1579854724787,
    },
    b28: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579558600372,
    },
    b29: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579508324590,
    },
    b30: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1580118604982,
    },
    b31: {
      entityIds: {
        to: "0xf3fe6cfa8fe228efaa14e54db2b024b2f5cc8bea",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580041273248,
    },
    b32: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579652671402,
    },
    b33: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1579885382816,
    },
    b34: {
      entityIds: {
        to: "0x84d29f34ce7b2c0ead2ff21d0c15b6f7c0ba55be",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580094866632,
    },
    b35: {
      entityIds: {
        to: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579648956755,
    },
    b36: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1580424827352,
    },
    b37: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1580007474826,
    },
    b38: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1579884032025,
    },
    b39: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0x8e9bbddad4adcac9bcd0f69f68cd3a865dcbd27d",
      },
      time: 1580322435082,
    },
    r0: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
      },
      time: 1628683178752,
    },
    r1: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
      },
      time: 1627730030640,
    },
    r2: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
      time: 1626649248873,
    },
    r3: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
      time: 1627414620701,
    },
    r4: {
      entityIds: {
        to: "0x8cfd5ecfe6a5b5316a687da3b84bbbfac85bdce1",
        from: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
      time: 1627767070935,
    },
    r5: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
      time: 1626193705239,
    },
    r6: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
      time: 1626288390335,
    },
    r7: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
      },
      time: 1628570278211,
    },
    r8: {
      entityIds: {
        to: "0x84d29f34ce7b2c0ead2ff21d0c15b6f7c0ba55be",
        from: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
      },
      time: 1628102690120,
    },
    r9: {
      entityIds: {
        to: "0xfcb21b10dbfd36d43da9f2cdf4ade9aa0ae0cea7",
        from: "0xe26853d7b4acd167bc23f8bfea4afd0795ee7cbb",
      },
      time: 1627805727668,
    },
    r10: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
      time: 1628129790779,
    },
    r11: {
      entityIds: {
        to: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
        from: "0x9b7e69aef739afb8a6587b66dfebdf3b308c20b6",
      },
      time: 1625794960150,
    },
    r12: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
      },
      time: 1626945105626,
    },
    r13: {
      entityIds: {
        to: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
        from: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
      },
      time: 1627415639668,
    },
    r14: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0xb96b815724aaab085c5ab8b5aa57dfd1f80dbc0d",
      },
      time: 1627204207491,
    },
    r15: {
      entityIds: {
        to: "0xebcbdd0fa0c5419ecafbebec3d9f1944b9e15ced",
        from: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
      },
      time: 1627112157932,
    },
    r16: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
      },
      time: 1628543246465,
    },
    r17: {
      entityIds: {
        to: "0x5a2f4b75ef66b97e1c195a4a1cb6aa65b57d4773",
        from: "0x1b6ef00e4f136ce76cc31ad22a38a9dfa6fcaa86",
      },
      time: 1627474448769,
    },
    r18: {
      entityIds: {
        to: "0xb9b6ee5fcaa8a1a8d2ff3f38ce858f0fd8b0d942",
        from: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
      },
      time: 1627824827313,
    },
    r19: {
      entityIds: {
        to: "0xdfabc3fc77d9fa010c7ebd97ce6b63d68cbfba7f",
        from: "0xca38848ac7bbb6bbec5e45be6ee4ef1bb809bf9a",
      },
      time: 1628883517321,
    },
  },
  entityTypes: {
    good: {
      typeLabel: "Other Addresses",
      color: "#2E86C1",
      typeGlyph: true,
      order: 2,
    },
    bad: {
      typeLabel: "Suspicious Addresses",
      color: "#CB4335",
      typeGlyph: true,
      order: 1,
    },
    target: {
      typeLabel: "Hack Targets",
      color: "#28B463",
      typeGlyph: true,
      order: 0,
    },
  },
};
<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="@ci/theme/kg/css/examples.css" />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div id="my-timeline" style="height: 100vh"></div>
    <script type="module" src="./code.jsx"></script>
  </body>
</html>
#tooltip > span {
  background-color: #3d4852;
  padding: 2.5px 5px;
  border-radius: 5px;
}

#tooltip {
  display: none;
  align-items: center;
  position: absolute;
  transform: translate(0, -50%);
  transform-origin: left center;
  pointer-events: none;
  z-index: 10;
  white-space: nowrap;
}

#tooltip-arrow {
  width: 0;
  height: 0;
  border-top: 10px solid transparent;
  border-bottom: 10px solid transparent;
  border-right: 10px solid #3d4852;
}

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.