Add visjs to standalone html

Hi,

I was looking at this example for wrapping a js library: Wrapping a JavaScript library — Bokeh 2.4.2 Documentation

Not entirely sure about the TS part of the code. If I wanted to use something like this:
https://visjs.github.io/vis-network/examples/

I tried something like this (getting a ton of errors):

import numpy as np

from bokeh.core.properties import Instance, String
from bokeh.io import show
from bokeh.models import ColumnDataSource, LayoutDOM
from bokeh.util.compiler import TypeScript

TS_CODE = """
import {LayoutDOM, LayoutDOMView} from "models/layouts/layout_dom"
import {ColumnDataSource} from "models/sources/column_data_source"
import {LayoutItem} from "core/layout"
import * as p from "core/properties"

declare namespace vis {
  class Network {
    constructor(el: HTMLElement, data: object, OPTIONS: object)
    setData(data: vis.DataSet): void

  }

  class DataSet {
    add(data: unknown): void
  }
}

const OPTIONS = {
    nodes: {
      shape: "dot",
      size: 16
    },
    layout: {
      randomSeed: 34
    },
    physics: {
      forceAtlas2Based: {
        gravitationalConstant: -26,
        centralGravity: 0.005,
        springLength: 230,
        springConstant: 0.18
      },
      maxVelocity: 146,
      solver: "forceAtlas2Based",
      timestep: 0.35,
      stabilization: {
        enabled: true,
        iterations: 2000,
        updateInterval: 25
      }
    }
  }

export class Network extends LayoutDOMView {
  model: Network

  private _graph: vis.Network

  initialize(): void {
    super.initialize()

    const url = "https://cdnjs.cloudflare.com/ajax/libs/vis/4.16.1/vis.min.js"
    const script = document.createElement("script")
    script.onload = () => this._init()
    script.async = false
    script.src = url
    document.head.appendChild(script)
  }

  private _init(): void {
    this._graph = new vis.Network(this.el, this.get_data(), OPTIONS)

    this.connect(this.model.data_source.change, () => {
      this._graph.setData(this.get_data())
    })
  }

  get_data(): vis.DataSet {
    const data = new vis.DataSet()
    const source = this.model.data_source
    for (let i = 0; i < source.get_length()!; i++) {
      data.add({
        nodes: source.data[this.model.nodes][i],
        egdes: source.data[this.model.egdes][i],
      })
    }
    return data
  }

  get child_models(): LayoutDOM[] {
    return []
  }

  _update_layout(): void {
    this.layout = new LayoutItem()
    this.layout.set_sizing(this.box_sizing())
  }
}
export namespace Network {
  export type Attrs = p.AttrsOf<Props>

  export type Props = LayoutDOM.Props & {
    nodes: p.Property<string>
    egdes: p.Property<string>
    data_source: p.Property<ColumnDataSource>
  }
}

export interface Network extends Network.Attrs {}

export class Network extends LayoutDOM {
  properties: Network.Props

  constructor(attrs?: Partial<Network.Attrs>) {
    super(attrs)
  }

  static __name__ = "Network"

  static init_Network() {
    this.prototype.default_view = NetworkView

    this.define<Network.Props>({
      nodes:            [ p.String   ],
      egdes:            [ p.String   ],
      data_source:  [ p.Instance ],
    })
  }
}
"""

# This custom extension model will have a DOM view that should layout-able in
# Bokeh layouts, so use ``LayoutDOM`` as the base class. If you wanted to create
# a custom tool, you could inherit from ``Tool``, or from ``Glyph`` if you
# wanted to create a custom glyph, etc.
class Network(LayoutDOM):

    # The special class attribute ``__implementation__`` should contain a string
    # of JavaScript code that implements the browser side of the extension model.
    __implementation__ = TypeScript(TS_CODE)

    # Below are all the "properties" for this model. Bokeh properties are
    # class attributes that define the fields (and their types) that can be
    # communicated automatically between Python and the browser. Properties
    # also support type validation. More information about properties in
    # can be found here:
    #
    #    https://docs.bokeh.org/en/latest/docs/reference/core/properties.html#bokeh-core-properties

    # This is a Bokeh ColumnDataSource that can be updated in the Bokeh
    # server by Python code
    data_source = Instance(ColumnDataSource)

    # The vis.js library that we are wrapping expects data for x, y, and z.
    # The data will actually be stored in the ColumnDataSource, but these
    # properties let us specify the *name* of the column that should be
    # used for each field.
    nodes = String
    edges = String



nodes = np.arange(0, 300, 10)
egdes = np.arange(0, 300, 10)

source = ColumnDataSource(data=dict(nodes=nodes, egdes=egdes))

surface = Network(nodes="nodes", edges="edges", data_source=source, width=600, height=600)

show(surface)