Search

Angular Integration

Frameworks

Use Angular to create time bar and chart with font icons and tooltips.

Angular Integration
View live example →

This demo is a version of Time Periods demo and uses Angular version 12.

This demo shows how to use the KeyLines Angular component to:

  • Declare multiple components - KeyLines wraps chart and time bar elements with kl-components
  • Add font icons and tooltips
  • Set options on the chart
  • Listen for change events on the time bar and capture them on the controller to filter the chart

Angular Component

We've written the source code and chart component in ES6 and TypeScript. We've also bundled the demo, chart component and Angular into a single file using Webpack, and transpiled the code to JavaScript using Babel.

See also

Tutorial: Angular Tutorial

KeyLines Angular component: Angular Reference

Angular official page: angular.io

Key functions used:

import KeyLines from "keylines";

import "core-js";
import "zone.js";

import { OnInit } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { BrowserModule } from "@angular/platform-browser";
import { NgModule, enableProdMode, Component } from "@angular/core";

import {
  Chart,
  TimeBar,
  TimeBarOptions,
  ChartOptions,
  ChartAllEventProps,
  ChartPointerEventProps,
  SelectionOptions,
  LayoutOptions,
  TimeBarAllEventProps,
} from "keylines";

// import the KeyLines components
import { KlComponent, KlComponents, KlComponentsService } from "./angular-keylines";
import { LeftPanel, RightPanel } from "./angular-demo";

import { chartData, timebarData } from "./data";
// @ts-ignore - webpack resolves ngResource CSS imports to a string at build time.
import chartFilterStyles from "./angularchartfilter.css?ngResource";

// enable production mode
enableProdMode();

                  
               
                                                  
 

export class Tooltip {
  constructor(
    public start        ,
    public end        ,
    public left        ,
    public top        ,
    public tooltipClass        ,
    public arrowClass        
  ) {}
}

@Component({
  selector: "kl-container",
  template: `
    <div class="chart-wrapper demo-cols">
      <kl-leftPanel class="flex1">
        <span
          #ngTooltip
          id="tooltip"
          class="{{ this.model.tooltipClass }}"
          [style.left]="this.model.left"
          [style.top]="this.model.top"
        >
          <div class="{{ this.model.arrowClass }}"></div>
          <tr>
            <td class="table-cell"><b>Appointed on: </b></td>
            <td>{{ this.model.start }}</td>
          </tr>
          <tr>
            <td class="table-cell"><b>Resigned on: </b></td>
            <td>{{ this.model.end }}</td>
          </tr>
        </span>
        <div id="lhsVisual" class="toggle-content is-visible">
          <kl-components (klReady)="klChartReady($event)">
            <kl-component
              class="flex1"
              klType="chart"
              klContainerClass="klchart klchart-timebar"
              [klOptions]="chartOptions"
              (klEvents)="klChartEvents($event)"
            >
            </kl-component>
            <kl-component
              klType="timebar"
              klContainerClass="kltimebar"
              [klOptions]="timebarOptions"
              (klEvents)="klTimebarEvents($event)"
            >
            </kl-component>
          </kl-components>
        </div>
        <div id="lhsSource" class="toggle-content">
          <iframe
            id="sourceView"
            style="width: 100%; height: 100%; border: none;"
            src="source-angularchartfilter.js.htm"
            scrolling="no"
          ></iframe>
        </div>
      </kl-leftPanel>
      <kl-rightPanel
        name="angularchartfilter"
        title="Angular Integration: Time"
        description="Use Angular and the time bar to filter chart items."
      >
        <fieldset>
          <legend>Interaction</legend>
          <ul>
            <li>Use the time bar controls to see changes over time</li>
            <li>Hover/click a link to to show the duration of an individual's directorship</li>
            <li>Multi-select up to three items to highlight their neighbours</li>
          </ul>
        </fieldset>
        <fieldset>
          <legend>Data Format</legend>
          <p>
            The time bar data format is similar to that used for the chart. It is possible to pass
            the same data object to both components.
          </p>
        </fieldset>
      </kl-rightPanel>
    </div>
  `,
  styles: [chartFilterStyles],
})
export class ChartFilterComponent                   {
          chart        ;
          timebar          ;
  // Define some options for the chart
         chartOptions               = {
    logo: { u: "/images/Logo.png" },
    overview: { icon: false, shown: false },
    iconFontFamily: "Font Awesome 5 Free",
    handMode: true,
    hover: 0,
    selectedNode: {
      fbc: "rgba(0,0,0,0)",
    },
    selectedLink: {
      fbc: "rgba(0,0,0,0)",
    },
  };
  // Define some options for the timebar
         timebarOptions                 = {
    histogram: {
      colour: "#E64669",
      highlightColour: "#DD0031",
      markColour: "rgb(192, 192, 192)",
      markHiColour: "rgb(105, 105, 105)",
    },
  };

  model = new Tooltip("", "", "", "", "hidden", "arrow");
  marks = [
    {
      dt1: new Date("01 Jan 2018 01:00:00"),
      dt2: new Date("01 Jan 2050 01:00:00"),
    },
  ];
  greyColours = ["rgb(105, 105, 105)", "rgb(192, 192, 192)"];

  // only style the first 3 selections
  selectionColours = [
    ["#9600d5", "#d0a3cb"],
    ["rgb(0, 191, 255)", "#8dd8f8"],
    ["rgb(50,205,50)", "#afdaae"],
  ];

  ngOnInit() {
    document.fonts.load('24px "Font Awesome 5 Free"');
  }

  klChartReady([chart, timebar]                  ) {
    this.chart = chart;
    this.timebar = timebar;

    chartData.items.forEach((element) => {
      if (element.type === "node") {
        element.fi = {
          c: this.greyColours[0],
          t: element.d.type === "person" ? "fas fa-user" : "fas fa-building",
        };
      }
    });

    this.chart.load(chartData);
    this.timebar.load(timebarData);
    this.timebar.mark(this.marks);

    this.chart.zoom("fit");
    this.timebar.zoom("fit");
  }

  // will receive events for the timebar
  klTimebarEvents({ name }        ) {
    if (name === "change") {
      this.onTimebarChange();
    }
  }

  // will receive events for the chart
  klChartEvents({ name, args }        ) {
    if (name === "selection-change" && this.chart?.selection()) {
      this.highlightSelections();
    } else if (name === "hover" || name === "pointer-down" || name === "drag-move") {
      this.toggleTooltip(args                          );
    }
  }

  getDateFromTimestamp(timestamp        ) {
    return timestamp ? new Date(timestamp).toDateString().slice(4) : "n/a";
  }

  toggleTooltip({ id, x, y }                        ) {
    if (this.chart) {
      const item = id ? this.chart.getItem(id) : null;
      const viewWidth = this.chart.viewOptions().width;

      if (item && item.type === "link") {
        const timebarItem = timebarData.items.filter((tbItem) => tbItem.id === item.id)     
                                             
           ;
        this.model.start = this.getDateFromTimestamp(timebarItem[0].dt[0].dt1);
        this.model.end = this.getDateFromTimestamp(timebarItem[0].dt[0].dt2);

        // style tooltip to left of cursor if it's x position + width exceeds
        // the remaining chart space.
        if (viewWidth && viewWidth > x + 250) {
          this.model.top = `${y - 24}px`;
          this.model.left = `${x + 22}px`;
          this.model.tooltipClass = "";
        } else {
          this.model.top = `${y - 24}px`;
          this.model.left = `${x - 218}px`;
          this.model.tooltipClass = "right";
        }
      } else {
        this.model.tooltipClass = "hidden";
      }
    }
  }

  buildItemStyling(item     , width        , colour        , border = false) {
    if (item.type === "node") {
      return {
        id: item.id,
        fi: {
          c: colour,
          t: item.d.type === "person" ? "fas fa-user" : "fas fa-building",
        },
        b: border ? colour : null,
      };
    }
    // else it is a link
    return { id: item.id, w: width || 4, c: colour };
  }

  highlightSelections() {
    if (!this.chart || !this.timebar) return;

    this.timebar.selection([]);
    const timebarSelection                     = [];
    const chartProperties                                                           = {};
    // set default colouring
    this.chart.each({ type: "all" }, (item) => {
      chartProperties[item.id] = this.buildItemStyling(
        item,
        3,
        item.type === "node" ? this.greyColours[0] : this.greyColours[1]
      );
    });

    let selectedIds = this.chart.selection();

    if (selectedIds) {
      if (selectedIds.length > this.selectionColours.length) {
        selectedIds = selectedIds.slice(0, this.selectionColours.length);
        this.chart.selection(selectedIds);
      }

      selectedIds.forEach((id, index) => {
        let neighbouringNodes      = [];
        let links           = [];
        const item = this.chart?.getItem(id);
        const colour =
          index < this.selectionColours.length
            ? this.selectionColours[index][0]
            : this.greyColours[1];
        const linkColour = this.selectionColours[index][1];

        if (item && item.type === "node") {
          // all: true - applies styles to hidden nodes + links not in current time range
          const neighbours = this.chart?.graph().neighbours(id, { all: true });
          if (neighbours && neighbours.links) {
            links = neighbours.links;
            neighbouringNodes = neighbours.nodes;
          }

          // colour node
          chartProperties[id] = this.buildItemStyling(item, 3, colour, true);
          links.forEach((link        ) => {
            const linkItem = this.chart?.getItem(link);
            chartProperties[link] = this.buildItemStyling(linkItem, 5, linkColour);
          });
        } else if (item && item.type === "link") {
          links.push(id);
          neighbouringNodes.push(item.id1, item.id2);

          // colour link
          chartProperties[id] = this.buildItemStyling(item, 5, colour);
        }
        // colour neighbour nodes
        neighbouringNodes.forEach((neighbourId        ) => {
          if (
            chartProperties[neighbourId].fi.c === this.greyColours[0] &&
            index < this.selectionColours.length
          ) {
            chartProperties[neighbourId] = this.buildItemStyling(
              this.chart?.getItem(neighbourId),
              3,
              this.selectionColours[index][1]
            );
          }
        });
        // and select in the timebar
        timebarSelection.push({
          id: links,
          index,
          c: colour,
        });
      });

      this.timebar.selection(timebarSelection);
      this.chart.setProperties(Object.keys(chartProperties).map((key) => chartProperties[key]));
    }
  }

  doLayout() {
    if (!this.chart) return;
    const opts                = {
      time: 500,
      mode: "adaptive",
      easing: "linear",
      straighten: false,
    };
    this.chart.layout("organic", opts);
  }

  onTimebarChange() {
    if (!this.chart || !this.timebar) return;
    // filter the chart to show only items in the new range
    this.chart.filter(this.timebar.inRange, { animate: false, type: "link" });
    // and then adjust the chart's layout
    this.doLayout();
  }
}

@NgModule({
  imports: [BrowserModule],
  declarations: [ChartFilterComponent, KlComponent, KlComponents, LeftPanel, RightPanel],
  providers: [KlComponentsService],
  bootstrap: [ChartFilterComponent],
})
export class AppModule {}

platformBrowserDynamic().bootstrapModule(AppModule);

// preprocess does not play nicely with the ng loader so @include does not work
//@ts-expect-error
window.toggleKeyLinesFullScreen = function (onFullScreen     ) {
  if (KeyLines.fullScreenCapable()) {
    const elem = document.getElementById("fullscreen") ;
    KeyLines.toggleFullScreen(elem, onFullScreen);
  }
};

//@ts-expect-error
window.zoomKeyLinesToFit = function () {
  Object.keys(KeyLines.components).forEach(function (id) {
    var component = KeyLines.components[id];
    if (id.indexOf("chart") !== -1) {
      component.zoom("fit");
    }
  });
};

//@ts-expect-error
window.isKeyLinesFullScreenCapable = function () {
  return KeyLines.fullScreenCapable();
};
import {
  Component,
  ElementRef,
  Input,
  Output,
  EventEmitter,
  Injectable,
  AfterViewInit,
  OnDestroy,
  OnChanges,
  SimpleChange,
  ContentChildren,
  ViewChild,
  NgZone,
} from "@angular/core";

import * as kl from "keylines";
import KeyLines from "keylines";

@Injectable()
export class KlComponentsService {
  constructor(private ngZone        ) {}
  create(
    componentDefinitions                ,
    pathToImages        
  )                                     {
    // KeyLines paths configuration
    KeyLines.paths({ images: pathToImages });
    // KeyLines create components, running the KeyLines create call outside Angular
    // to prevent call of requestAnimationFrame from KeyLines triggering Angular change detection.
    return this.ngZone.runOutsideAngular(() => {
      return KeyLines.create(componentDefinitions);
    });
  }
}

@Component({
  selector: "kl-component",
  template: '<div #container [ngClass]="containerClass" [ngStyle]="style"></div>',
})
export class KlComponent                                 {
  @Input() id         = ""; //optional

  @Input("ngStyle") style     ; //optional

  @Input("klType") type                      = "chart"; // optional
  @Input("klOptions") options                                      = {}; // optional

  @Input("klContainerClass") containerClass         = ""; // optional

  @Output("klReady") klReady = new EventEmitter(); // optional
  @Output("klEvents") klEvents = new EventEmitter(); // optional

  // Save the reference of the container element: see #container in the template
  @ViewChild("container", { static: false })
          containerElement             ;
  // The KeyLines component
          component                        ;

  constructor(private ngZone        ) {}

  isChart(component                       )                        {
    return this.type === "chart";
  }

  // lifecycle hooks
  ngOnChanges(changes                                          ) {
    const { options } = changes;
    // Refresh the options when necessary
    if (options && !options.isFirstChange()) {
      this.refreshOptions(options.currentValue);
    }
  }
  ngOnDestroy() {
    if (this.component) {
      // ensure the component cleans up its resources
      this.component.destroy();
    }
  }

  // Kl instructions
  getHeader()               {
    return {
      container: this.containerElement ? this.containerElement.nativeElement : undefined,
      type: this.type,
      options: this.options,
    };
  }

  setUpComponent(component                       ) {
    // save the reference of the component
    this.component = component;
    // trigger a klReady event with the component reference
    this.klReady.emit(component);
    // attach the component events
    this.registerEvent();
  }

  registerEvent() {
    function emitEvent(                   props     )       {
      const klEvent = { name: props.name, args: props.event, preventDefault: false };
      // dispatch the event to the parent within the Angular zone
      this.ngZone.run(() => this.klEvents.emit(klEvent));
      if (klEvent.preventDefault && props.event && props.event.preventDefault) {
        props.event.preventDefault();
      }
    }
    if (this.component) {
      if (this.isChart(this.component)) {
        this.component.on("all", emitEvent.bind(this));
      } else {
        this.component.on("all", emitEvent.bind(this));
      }
    }
  }

  refreshOptions(options                                     ) {
    if (this.component) {
      // Use type guard to allow TypeScript to infer type and prevent errors
      if (this.isChart(this.component)) {
        this.component.options(options);
      } else {
        this.component.options(options);
      }
    }
  }
}

@Component({
  selector: "kl-components",
  template: "<ng-content></ng-content>",
})
export class KlComponents                          {
  @Input("klImagesPath") pathToImages = ""; // optional
  @Output("klReady") klReady = new EventEmitter(); // optional

  // save the KeyLines service
          KlComponentsService                     ;
  // get the list of the children components
  // http://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html
  @ContentChildren(KlComponent)
          components                ;

  // constructor
  constructor(KlComponentsService                     ) {
    this.KlComponentsService = KlComponentsService;
  }

  // lifecycle hooks
  ngAfterViewInit() {
    if (!this.components) throw "Could not find kl-component declaration";
    // iterate over the list of children components to create the KeyLines definition of components
    const componentDefinitions = this.components.map((component) => component.getHeader());
    this.createComponents(componentDefinitions);
  }

  // KL instructions
  createComponents(componentDefinitions                ) {
    // use the KeyLines service to create the components
    this.KlComponentsService.create(componentDefinitions, this.pathToImages)
      .then((components) => this.notifyComponents(components))
      .catch((error     ) => error);
  }

  notifyComponents(components                                                   ) {
    // ensure that we have an array of components
    if (!Array.isArray(components)) {
      components = [components];
    }
    this.klReady.emit(components);
    // finalise the set up of registered components
    if (this.components) {
      this.components.forEach((component, index) => {
        component.setUpComponent((components                             )[index]);
      });
    }
  }
}
import { Component, Input, ViewChild, ElementRef } from "@angular/core";

@Component({
  selector: "kl-leftPanel",
  template: ` <ng-content></ng-content>`,
})
export class LeftPanel {}
@Component({
  selector: "kl-rightPanel",
  template: `
    <div class="rhs citext flex-column flex">
      <div class="title-bar">
        <h3 class="flex1">Angular Integration</h3>
        <div class="buttons flex" id="titlebarbuttons">
          <a
            class="btn btn-label disabled fshide"
            href="#"
            data-toggle="tooltip"
            id="fullscreenDisabled"
          >
            <i class="fa fa-compress"></i>
          </a>
          <a class="btn btn-label" href="#" data-toggle="tooltip" id="fullscreenButton">
            <i class="fa fa-expand"></i>
          </a>
        </div>
      </div>
      <div class="tabsdiv tab" data-tab-group="rhs">
        <a
          class="btn btn-spaced fshide rhs-toggle fancy-button"
          id="closeRHS"
          href="#"
          data-toggle="tooltip"
        >
          <i class="fa fa-chevron-right"></i>
        </a>
        <button class="tablinks active" name="controlsTab" type="button">Controls</button>
        <button class="tablinks" name="aboutTab" type="button">About</button>
        <button class="tablinks" name="sourceTab" type="button">Source</button>
      </div>
      <div class="tab-content-panel flex1" data-tab-group="rhs">
        <div class="toggle-content is-visible tabcontent" id="controlsTab">
          <div class="cicontent">
            <img class="kl-center" src="images/{{ name }}/angular.png" width="40%" />
            <ng-content></ng-content>
          </div>
        </div>
        <div id="aboutTab" #aboutTab class="toggle-content tabcontent"></div>
        <div id="sourceTab" #sourceTab class="toggle-content tabcontent"></div>
      </div>
    </div>
  `,
})
export class RightPanel {
  @Input() name = "";
  @Input() title = "";
  @Input() description = "";
  @ViewChild("sourceTab", { static: false }) sourceTabEl;
  @ViewChild("aboutTab", { static: false }) aboutTabEl;

  ngAfterViewInit() {
    const sourcePanel = document.getElementById("sourcePanel");
    const aboutPanel = document.getElementById("aboutPanel");
    if (sourcePanel && aboutPanel) {
      // re-assign parent of child elements, rather than copy HTML so as to not remove any event handlers
      this.sourceTabEl.nativeElement.appendChild(sourcePanel);
      for (const child of Array.from(sourcePanel.children)) {
        this.sourceTabEl.nativeElement.appendChild(child);
      }
      const aboutTemplate = aboutPanel.innerHTML;
      this.aboutTabEl.nativeElement.innerHTML = aboutTemplate;
      // @ts-ignore
      if (window.setupTabPanel) window.setupTabPanel();
    }
  }
}
import { ChartData, TimeBarData } from "keylines";

export const chartData = {
  type: "LinkChart",
  // @ts-ignore
  items: [
    {
      type: "node",
      id: "Brooke Fields",
      t: "Brooke Fields",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Gina Carlson",
      t: "Gina Carlson",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Guillermo Vaughn",
      t: "Guillermo Vaughn",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Rose Ingram",
      t: "Rose Ingram",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Jeannie Wolfe",
      t: "Jeannie Wolfe",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Dave Rice",
      t: "Dave Rice",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Paul Watts",
      t: "Paul Watts",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Danny Matthews",
      t: "Danny Matthews",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Anthony Mitchell",
      t: "Anthony Mitchell",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Alfred Hicks",
      t: "Alfred Hicks",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Adrian Mcdaniel",
      t: "Adrian Mcdaniel",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Kerry Waters",
      t: "Kerry Waters",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Felix Floyd",
      t: "Felix Floyd",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Noel Luna",
      t: "Noel Luna",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Tami Lindsey",
      t: "Tami Lindsey",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Damon Douglas",
      t: "Damon Douglas",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Diana Greene",
      t: "Diana Greene",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Gary King",
      t: "Gary King",
      d: {
        type: "person",
      },
    },
    {
      type: "node",
      id: "Phantom Corporation",
      t: "Phantom Corporation",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Melon Arts",
      t: "Melon Arts",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Green",
      t: "Green",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Marblightning",
      t: "Marblightning",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Cycloration",
      t: "Cycloration",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Bluetronics",
      t: "Bluetronics",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Summitechnologies",
      t: "Summitechnologies",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Cloudwalk",
      t: "Cloudwalk",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Jettechs",
      t: "Jettechs",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Quadbridge",
      t: "Quadbridge",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Crow Navigations",
      t: "Crow Navigations",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Grasshopper Co.",
      t: "Grasshopper Co.",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Daydream Security",
      t: "Daydream Security",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Joytechs",
      t: "Joytechs",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Dwarfoods",
      t: "Dwarfoods",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Cliffoods",
      t: "Cliffoods",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Vinedustries",
      t: "Vinedustries",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Bansheewares",
      t: "Bansheewares",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Moonshine",
      t: "Moonshine",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Mapleway",
      t: "Mapleway",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Diamond Aviation",
      t: "Diamond Aviation",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Grotto Corp",
      t: "Grotto Corp",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Root Aviation",
      t: "Root Aviation",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "White Wolfoods",
      t: "White Wolfoods",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Greenetworks",
      t: "Greenetworks",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Honeytelligence",
      t: "Honeytelligence",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Tempestechnologies",
      t: "Tempestechnologies",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Phoenixland",
      t: "Phoenixland",
      d: {
        type: "company",
      },
    },
    {
      type: "node",
      id: "Crystalsun",
      t: "Crystalsun",
      d: {
        type: "company",
      },
    },
    {
      type: "link",
      id: "Brooke Fields-Phantom Corporation",
      id1: "Brooke Fields",
      id2: "Phantom Corporation",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Melon Arts",
      id1: "Brooke Fields",
      id2: "Melon Arts",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Green",
      id1: "Brooke Fields",
      id2: "Green",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Marblightning",
      id1: "Brooke Fields",
      id2: "Marblightning",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Cycloration",
      id1: "Brooke Fields",
      id2: "Cycloration",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Bluetronics",
      id1: "Gina Carlson",
      id2: "Bluetronics",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Summitechnologies",
      id1: "Gina Carlson",
      id2: "Summitechnologies",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Cloudwalk",
      id1: "Gina Carlson",
      id2: "Cloudwalk",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Jettechs",
      id1: "Gina Carlson",
      id2: "Jettechs",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Quadbridge",
      id1: "Gina Carlson",
      id2: "Quadbridge",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Guillermo Vaughn-Crow Navigations",
      id1: "Guillermo Vaughn",
      id2: "Crow Navigations",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Rose Ingram-Grasshopper Co.",
      id1: "Rose Ingram",
      id2: "Grasshopper Co.",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Rose Ingram-Daydream Security",
      id1: "Rose Ingram",
      id2: "Daydream Security",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Jeannie Wolfe-Joytechs",
      id1: "Jeannie Wolfe",
      id2: "Joytechs",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Dave Rice-Dwarfoods",
      id1: "Dave Rice",
      id2: "Dwarfoods",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Paul Watts-Cliffoods",
      id1: "Paul Watts",
      id2: "Cliffoods",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Paul Watts-Vinedustries",
      id1: "Paul Watts",
      id2: "Vinedustries",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Danny Matthews-Bansheewares",
      id1: "Danny Matthews",
      id2: "Bansheewares",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Anthony Mitchell-Moonshine",
      id1: "Anthony Mitchell",
      id2: "Moonshine",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Anthony Mitchell-Mapleway",
      id1: "Anthony Mitchell",
      id2: "Mapleway",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Alfred Hicks-Diamond Aviation",
      id1: "Alfred Hicks",
      id2: "Diamond Aviation",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Adrian Mcdaniel-Grotto Corp",
      id1: "Adrian Mcdaniel",
      id2: "Grotto Corp",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Kerry Waters-Root Aviation",
      id1: "Kerry Waters",
      id2: "Root Aviation",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Kerry Waters-White Wolfoods",
      id1: "Kerry Waters",
      id2: "White Wolfoods",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Felix Floyd-Greenetworks",
      id1: "Felix Floyd",
      id2: "Greenetworks",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Noel Luna-Honeytelligence",
      id1: "Noel Luna",
      id2: "Honeytelligence",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Tami Lindsey-Tempestechnologies",
      id1: "Tami Lindsey",
      id2: "Tempestechnologies",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Tami Lindsey-Phoenixland",
      id1: "Tami Lindsey",
      id2: "Phoenixland",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Damon Douglas-Crystalsun",
      id1: "Damon Douglas",
      id2: "Crystalsun",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Damon Douglas-Phantom Corporation",
      id1: "Damon Douglas",
      id2: "Phantom Corporation",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Diana Greene-Melon Arts",
      id1: "Diana Greene",
      id2: "Melon Arts",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Diana Greene-Green",
      id1: "Diana Greene",
      id2: "Green",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gary King-Marblightning",
      id1: "Gary King",
      id2: "Marblightning",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Cycloration",
      id1: "Brooke Fields",
      id2: "Cycloration",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Bluetronics",
      id1: "Brooke Fields",
      id2: "Bluetronics",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Summitechnologies",
      id1: "Brooke Fields",
      id2: "Summitechnologies",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Cloudwalk",
      id1: "Brooke Fields",
      id2: "Cloudwalk",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Brooke Fields-Jettechs",
      id1: "Brooke Fields",
      id2: "Jettechs",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Quadbridge",
      id1: "Gina Carlson",
      id2: "Quadbridge",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Crow Navigations",
      id1: "Gina Carlson",
      id2: "Crow Navigations",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Grasshopper Co.",
      id1: "Gina Carlson",
      id2: "Grasshopper Co.",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Daydream Security",
      id1: "Gina Carlson",
      id2: "Daydream Security",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gina Carlson-Joytechs",
      id1: "Gina Carlson",
      id2: "Joytechs",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Guillermo Vaughn-Dwarfoods",
      id1: "Guillermo Vaughn",
      id2: "Dwarfoods",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Rose Ingram-Cliffoods",
      id1: "Rose Ingram",
      id2: "Cliffoods",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Jeannie Wolfe-Vinedustries",
      id1: "Jeannie Wolfe",
      id2: "Vinedustries",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Jeannie Wolfe-Bansheewares",
      id1: "Jeannie Wolfe",
      id2: "Bansheewares",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Dave Rice-Moonshine",
      id1: "Dave Rice",
      id2: "Moonshine",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Paul Watts-Mapleway",
      id1: "Paul Watts",
      id2: "Mapleway",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Danny Matthews-Diamond Aviation",
      id1: "Danny Matthews",
      id2: "Diamond Aviation",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Danny Matthews-Grotto Corp",
      id1: "Danny Matthews",
      id2: "Grotto Corp",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Anthony Mitchell-Root Aviation",
      id1: "Anthony Mitchell",
      id2: "Root Aviation",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Anthony Mitchell-White Wolfoods",
      id1: "Anthony Mitchell",
      id2: "White Wolfoods",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Alfred Hicks-Greenetworks",
      id1: "Alfred Hicks",
      id2: "Greenetworks",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Adrian Mcdaniel-Honeytelligence",
      id1: "Adrian Mcdaniel",
      id2: "Honeytelligence",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Adrian Mcdaniel-Tempestechnologies",
      id1: "Adrian Mcdaniel",
      id2: "Tempestechnologies",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Kerry Waters-Phoenixland",
      id1: "Kerry Waters",
      id2: "Phoenixland",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Felix Floyd-Crystalsun",
      id1: "Felix Floyd",
      id2: "Crystalsun",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Felix Floyd-Phantom Corporation",
      id1: "Felix Floyd",
      id2: "Phantom Corporation",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Noel Luna-Melon Arts",
      id1: "Noel Luna",
      id2: "Melon Arts",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Noel Luna-Green",
      id1: "Noel Luna",
      id2: "Green",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Tami Lindsey-Marblightning",
      id1: "Tami Lindsey",
      id2: "Marblightning",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Tami Lindsey-Cycloration",
      id1: "Tami Lindsey",
      id2: "Cycloration",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Damon Douglas-Bluetronics",
      id1: "Damon Douglas",
      id2: "Bluetronics",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Damon Douglas-Summitechnologies",
      id1: "Damon Douglas",
      id2: "Summitechnologies",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Diana Greene-Cloudwalk",
      id1: "Diana Greene",
      id2: "Cloudwalk",
      a2: true,
      w: 3,
    },
    {
      type: "link",
      id: "Gary King-Jettechs",
      id1: "Gary King",
      id2: "Jettechs",
      a2: true,
      w: 3,
    },
  ],
};
export const timebarData = {
  items: [
    {
      id: "Brooke Fields-Phantom Corporation",
      dt: [
        {
          dt1: 1339014193119,
        },
      ],
    },
    {
      id: "Brooke Fields-Melon Arts",
      dt: [
        {
          dt1: 1247271160185,
        },
      ],
    },
    {
      id: "Brooke Fields-Green",
      dt: [
        {
          dt1: 1237397195464,
        },
      ],
    },
    {
      id: "Brooke Fields-Marblightning",
      dt: [
        {
          dt1: 1268721087691,
        },
      ],
    },
    {
      id: "Brooke Fields-Cycloration",
      dt: [
        {
          dt1: 1310952185992,
        },
      ],
    },
    {
      id: "Gina Carlson-Bluetronics",
      dt: [
        {
          dt1: 1191238914316,
          dt2: 1270569157085,
        },
      ],
    },
    {
      id: "Gina Carlson-Summitechnologies",
      dt: [
        {
          dt1: 1276109390365,
          dt2: 1348661017536,
        },
      ],
    },
    {
      id: "Gina Carlson-Cloudwalk",
      dt: [
        {
          dt1: 1348270245074,
          dt2: 1412908707443,
        },
      ],
    },
    {
      id: "Gina Carlson-Jettechs",
      dt: [
        {
          dt1: 1415551838802,
          dt2: 1465786744438,
        },
      ],
    },
    {
      id: "Gina Carlson-Quadbridge",
      dt: [
        {
          dt1: 1459806246849,
        },
      ],
    },
    {
      id: "Guillermo Vaughn-Crow Navigations",
      dt: [
        {
          dt1: 1418792877334,
        },
      ],
    },
    {
      id: "Rose Ingram-Grasshopper Co.",
      dt: [
        {
          dt1: 1383109469104,
          dt2: 1498149360662,
        },
      ],
    },
    {
      id: "Rose Ingram-Daydream Security",
      dt: [
        {
          dt1: 1236890263269,
        },
      ],
    },
    {
      id: "Jeannie Wolfe-Joytechs",
      dt: [
        {
          dt1: 1266649394407,
          dt2: 1418563289105,
        },
      ],
    },
    {
      id: "Dave Rice-Dwarfoods",
      dt: [
        {
          dt1: 1435235563645,
          dt2: 1439593633782,
        },
      ],
    },
    {
      id: "Paul Watts-Cliffoods",
      dt: [
        {
          dt1: 1348460379175,
          dt2: 1430497186231,
        },
      ],
    },
    {
      id: "Paul Watts-Vinedustries",
      dt: [
        {
          dt1: 1342980716145,
        },
      ],
    },
    {
      id: "Danny Matthews-Bansheewares",
      dt: [
        {
          dt1: 1212592504689,
          dt2: 1506411552619,
        },
      ],
    },
    {
      id: "Anthony Mitchell-Moonshine",
      dt: [
        {
          dt1: 1294680086436,
          dt2: 1513775556429,
        },
      ],
    },
    {
      id: "Anthony Mitchell-Mapleway",
      dt: [
        {
          dt1: 1404224388156,
        },
      ],
    },
    {
      id: "Alfred Hicks-Diamond Aviation",
      dt: [
        {
          dt1: 1302567304700,
          dt2: 1435579135260,
        },
      ],
    },
    {
      id: "Adrian Mcdaniel-Grotto Corp",
      dt: [
        {
          dt1: 1275605687635,
          dt2: 1302441510735,
        },
      ],
    },
    {
      id: "Kerry Waters-Root Aviation",
      dt: [
        {
          dt1: 1357157613919,
          dt2: 1497198217881,
        },
      ],
    },
    {
      id: "Kerry Waters-White Wolfoods",
      dt: [
        {
          dt1: 1186565644914,
        },
      ],
    },
    {
      id: "Felix Floyd-Greenetworks",
      dt: [
        {
          dt1: 1281749075420,
          dt2: 1425911470613,
        },
      ],
    },
    {
      id: "Noel Luna-Honeytelligence",
      dt: [
        {
          dt1: 1428549346398,
          dt2: 1497935675353,
        },
      ],
    },
    {
      id: "Tami Lindsey-Tempestechnologies",
      dt: [
        {
          dt1: 1345276788162,
          dt2: 1402559251417,
        },
      ],
    },
    {
      id: "Tami Lindsey-Phoenixland",
      dt: [
        {
          dt1: 1272650321596,
        },
      ],
    },
    {
      id: "Damon Douglas-Crystalsun",
      dt: [
        {
          dt1: 1439239127664,
          dt2: 1446474483161,
        },
      ],
    },
    {
      id: "Damon Douglas-Phantom Corporation",
      dt: [
        {
          dt1: 1432259515171,
        },
      ],
    },
    {
      id: "Diana Greene-Melon Arts",
      dt: [
        {
          dt1: 1250937080868,
          dt2: 1272043917343,
        },
      ],
    },
    {
      id: "Diana Greene-Green",
      dt: [
        {
          dt1: 1388980546097,
        },
      ],
    },
    {
      id: "Gary King-Marblightning",
      dt: [
        {
          dt1: 1341532138270,
          dt2: 1348971910953,
        },
      ],
    },
    {
      id: "Brooke Fields-Cycloration",
      dt: [
        {
          dt1: 1252224410783,
        },
      ],
    },
    {
      id: "Brooke Fields-Bluetronics",
      dt: [
        {
          dt1: 1327698610449,
        },
      ],
    },
    {
      id: "Brooke Fields-Summitechnologies",
      dt: [
        {
          dt1: 1176476394850,
        },
      ],
    },
    {
      id: "Brooke Fields-Cloudwalk",
      dt: [
        {
          dt1: 1343570952015,
        },
      ],
    },
    {
      id: "Brooke Fields-Jettechs",
      dt: [
        {
          dt1: 1183735407623,
        },
      ],
    },
    {
      id: "Gina Carlson-Quadbridge",
      dt: [
        {
          dt1: 1203779987419,
          dt2: 1286114861583,
        },
      ],
    },
    {
      id: "Gina Carlson-Crow Navigations",
      dt: [
        {
          dt1: 1252864333111,
          dt2: 1332066374345,
        },
      ],
    },
    {
      id: "Gina Carlson-Grasshopper Co.",
      dt: [
        {
          dt1: 1318370099782,
          dt2: 1367155178043,
        },
      ],
    },
    {
      id: "Gina Carlson-Daydream Security",
      dt: [
        {
          dt1: 1445086054970,
          dt2: 1494164214919,
        },
      ],
    },
    {
      id: "Gina Carlson-Joytechs",
      dt: [
        {
          dt1: 1508949404869,
        },
      ],
    },
    {
      id: "Guillermo Vaughn-Dwarfoods",
      dt: [
        {
          dt1: 1439419710533,
        },
      ],
    },
    {
      id: "Rose Ingram-Cliffoods",
      dt: [
        {
          dt1: 1447743740784,
          dt2: 1475561870381,
        },
      ],
    },
    {
      id: "Jeannie Wolfe-Vinedustries",
      dt: [
        {
          dt1: 1302350026690,
          dt2: 1362601707946,
        },
      ],
    },
    {
      id: "Jeannie Wolfe-Bansheewares",
      dt: [
        {
          dt1: 1283669644884,
        },
      ],
    },
    {
      id: "Dave Rice-Moonshine",
      dt: [
        {
          dt1: 1232018923653,
          dt2: 1509860168360,
        },
      ],
    },
    {
      id: "Paul Watts-Mapleway",
      dt: [
        {
          dt1: 1210590359697,
          dt2: 1274000597065,
        },
      ],
    },
    {
      id: "Danny Matthews-Diamond Aviation",
      dt: [
        {
          dt1: 1440723155554,
          dt2: 1503407220276,
        },
      ],
    },
    {
      id: "Danny Matthews-Grotto Corp",
      dt: [
        {
          dt1: 1411610571654,
        },
      ],
    },
    {
      id: "Anthony Mitchell-Root Aviation",
      dt: [
        {
          dt1: 1412918383186,
          dt2: 1433401731854,
        },
      ],
    },
    {
      id: "Anthony Mitchell-White Wolfoods",
      dt: [
        {
          dt1: 1303392645020,
        },
      ],
    },
    {
      id: "Alfred Hicks-Greenetworks",
      dt: [
        {
          dt1: 1245395749674,
          dt2: 1343518747478,
        },
      ],
    },
    {
      id: "Adrian Mcdaniel-Honeytelligence",
      dt: [
        {
          dt1: 1244519754341,
          dt2: 1398795162709,
        },
      ],
    },
    {
      id: "Adrian Mcdaniel-Tempestechnologies",
      dt: [
        {
          dt1: 1293685825988,
        },
      ],
    },
    {
      id: "Kerry Waters-Phoenixland",
      dt: [
        {
          dt1: 1286331465363,
          dt2: 1321863520043,
        },
      ],
    },
    {
      id: "Felix Floyd-Crystalsun",
      dt: [
        {
          dt1: 1404871089274,
          dt2: 1435383669902,
        },
      ],
    },
    {
      id: "Felix Floyd-Phantom Corporation",
      dt: [
        {
          dt1: 1239896796491,
        },
      ],
    },
    {
      id: "Noel Luna-Melon Arts",
      dt: [
        {
          dt1: 1232612229592,
          dt2: 1489184683838,
        },
      ],
    },
    {
      id: "Noel Luna-Green",
      dt: [
        {
          dt1: 1179384154182,
        },
      ],
    },
    {
      id: "Tami Lindsey-Marblightning",
      dt: [
        {
          dt1: 1352564813420,
          dt2: 1365113284879,
        },
      ],
    },
    {
      id: "Tami Lindsey-Cycloration",
      dt: [
        {
          dt1: 1408263996000,
        },
      ],
    },
    {
      id: "Damon Douglas-Bluetronics",
      dt: [
        {
          dt1: 1365560827793,
          dt2: 1455292661790,
        },
      ],
    },
    {
      id: "Damon Douglas-Summitechnologies",
      dt: [
        {
          dt1: 1371837671366,
        },
      ],
    },
    {
      id: "Diana Greene-Cloudwalk",
      dt: [
        {
          dt1: 1368713370177,
          dt2: 1505960116022,
        },
      ],
    },
    {
      id: "Gary King-Jettechs",
      dt: [
        {
          dt1: 1212476185184,
          dt2: 1303569548447,
        },
      ],
    },
  ],
};
<!doctype html>
<html lang="en" style="background-color: #2d383f">
  <head>
    <meta charset="utf-8" />
    <title>Angular Integration</title>
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/keylines.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/minimalsdk.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/sdk-layout.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/demo.css" />
    <link
      rel="stylesheet"
      type="text/css"
      href="@fortawesome/[email protected]/css/fontawesome.css"
    />
    <link
      rel="stylesheet"
      type="text/css"
      href="@fortawesome/[email protected]/css/solid.css"
    />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <kl-container></kl-container>
    <script type="module" src="./code.js"></script>
  </body>
</html>
#tooltip {
  position: absolute;
  padding: 5px;
  display: block;
  color: black;
  float: left;
  border: 1px solid #ccc;
  background-color: #fff;
  z-index: 1000;
  width: 208px;
}

.arrow {
  position: absolute;
  top: 20px;
  left: -9px;
  border-width: 0px 0px 1px 1px;
  border-style: solid;
  border-color: #ccc;
  background-color: #fff;
  transform: rotateZ(45deg);
  height: 15px;
  width: 15px;
}

.right .arrow {
  top: 20px;
  left: 199px;
  transform: rotateZ(225deg);
}

.table-cell {
  text-align: right;
  padding: 5px;
}

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.