Custom copy tool in bokeh

I am trying to create a copy to clipboard using the new tool and save tool examples provided. This seems to work for the gesture tool but fails for the copy tool as shown here attempting to emulate the examples. This doesn’t display anything in the notebook. I’m looking for pointers on where this code is going wrong and the next steps to explore from the community.

from bokeh.core.properties import Instance
from bokeh.io import output_file, show, output_notebook
from bokeh.models import ColumnDataSource, Tool
from bokeh.plotting import figure
from bokeh.util.compiler import TypeScript

output_notebook()

TS_CODE = """
import {ActionTool, ActionToolView} from "models/tools/actions/action_tool"
import * as p from "core/properties"
import {tool_icon_copy_to_clipboard} from "styles/icons.css"

export class CopyToolView extends ActionToolView {
  override model: CopyTool

  async copy(): Promise<void> {
    const blob = await this.plot_view.to_blob()
    const item = new ClipboardItem({[blob.type]: Promise.resolve(blob)})
    await navigator.clipboard.write([item])
  }

  doit(): void {
        this.copy()
  }
}

export namespace CopyTool {
  export type Attrs = p.AttrsOf<Props>

  export type Props = ActionTool.Props
}

export interface CopyTool extends CopyTool.Attrs {}

export class CopyTool extends ActionTool {
  override properties: CopyTool.Props
  override __view_type__: CopyToolView

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

  static {
    this.prototype.default_view = CopyToolView

    this.register_alias("copy", () => new CopyTool())
  }

  override tool_name = "Copy"
  override icon = tool_icon_copy_to_clipboard

}
"""


class CopyTool(Tool):
    __implementation__ = TypeScript(TS_CODE)


source = ColumnDataSource(data=dict(x=[], y=[]))

plot = figure(x_range=(0, 10), y_range=(0, 10), tools=[CopyTool()])
plot.title.text = "Copy plot to clipboard"
plot.line(range(10), range(10))

show(plot)

Are you calling output_notebook after defining the custom extension? That is what “loads” the custom extension JS definition in to the browser JS runtime.