Files
Automaaval/dist/zacatraz/_internal/panel/models/echarts.ts
T
2026-03-14 21:48:05 +00:00

183 lines
5.4 KiB
TypeScript

import {ModelEvent} from "@bokehjs/core/bokeh_events"
import {div} from "@bokehjs/core/dom"
import type * as p from "@bokehjs/core/properties"
import type {Attrs} from "@bokehjs/core/types"
import {serializeEvent} from "./event-to-object"
import {HTMLBox, HTMLBoxView} from "./layout"
const mouse_events = [
"click", "dblclick", "mousedown", "mousemove", "mouseup", "mouseover", "mouseout",
"globalout", "contextmenu",
]
const events = [
"highlight", "downplay", "selectchanged", "legendselectchangedEvent", "legendselected",
"legendunselected", "legendselectall", "legendinverseselect", "legendscroll", "datazoom",
"datarangeselected", "timelineplaychanged", "restore", "dataviewchanged", "magictypechanged",
"geoselectchanged", "geoselected", "geounselected", "axisareaselected", "brush", "brushEnd",
"rushselected", "globalcursortaken", "rendered", "finished",
]
const all_events = mouse_events.concat(events)
export class EChartsEvent extends ModelEvent {
constructor(readonly type: string, readonly data: any, readonly query: string) {
super()
}
protected override get event_values(): Attrs {
return {model: this.origin, type: this.type, data: this.data, query: this.query}
}
static {
this.prototype.event_name = "echarts_event"
}
}
export class EChartsView extends HTMLBoxView {
declare model: ECharts
container: Element
_chart: any
_callbacks: Array<any>[] = []
override connect_signals(): void {
super.connect_signals()
const {width, height, renderer, theme, event_config, js_events, data} = this.model.properties
this.on_change(data, () => this._plot())
this.on_change([width, height], () => this._resize())
this.on_change([theme, renderer], () => {
this.render()
this._chart.resize()
})
this.on_change([event_config, js_events], () => this._subscribe())
}
override render(): void {
if (this._chart != null) {
(window as any).echarts.dispose(this._chart)
}
super.render()
this.container = div({style: {height: "100%", width: "100%"}})
const config = {width: this.model.width, height: this.model.height, renderer: this.model.renderer}
this._chart = (window as any).echarts.init(
this.container,
this.model.theme,
config,
)
this._plot()
this._subscribe()
this.shadow_el.append(this.container)
}
override remove(): void {
super.remove()
if (this._chart != null) {
(window as any).echarts.dispose(this._chart)
}
}
override after_layout(): void {
super.after_layout()
this._chart.resize()
}
_plot(): void {
if ((window as any).echarts == null) {
return
}
this._chart.setOption(this.model.data, this.model.options)
}
_resize(): void {
this._chart.resize({width: this.model.width, height: this.model.height})
}
_subscribe(): void {
if ((window as any).echarts == null) {
return
}
for (const [event_type, callback] of this._callbacks) {
this._chart.off(event_type, callback)
}
this._callbacks = []
for (const event_type in this.model.event_config) {
if (!all_events.includes(event_type)) {
console.warn(`Could not subscribe to unknown Echarts event: ${event_type}.`)
continue
}
const queries = this.model.event_config[event_type]
for (const query of queries) {
const callback = (event: any) => {
const processed = {...event}
processed.event = serializeEvent(event.event?.event)
const serialized = JSON.parse(JSON.stringify(processed))
this.model.trigger_event(new EChartsEvent(event_type, serialized, query))
}
if (query == null) {
this._chart.on(event_type, query, callback)
} else {
this._chart.on(event_type, callback)
}
this._callbacks.push([event_type, callback])
}
}
for (const event_type in this.model.js_events) {
if (!all_events.includes(event_type)) {
console.warn(`Could not subscribe to unknown Echarts event: ${event_type}.`)
continue
}
const handlers = this.model.js_events[event_type]
for (const handler of handlers) {
const callback = (event: any) => {
handler.callback.execute(this._chart, event)
}
if ("query" in handler) {
this._chart.on(event_type, handler.query, callback)
} else {
this._chart.on(event_type, callback)
}
this._callbacks.push([event_type, callback])
}
}
}
}
export namespace ECharts {
export type Attrs = p.AttrsOf<Props>
export type Props = HTMLBox.Props & {
data: p.Property<any>
options: p.Property<any>
event_config: p.Property<any>
js_events: p.Property<any>
renderer: p.Property<string>
theme: p.Property<string>
}
}
export interface ECharts extends ECharts.Attrs {}
export class ECharts extends HTMLBox {
declare properties: ECharts.Props
constructor(attrs?: Partial<ECharts.Attrs>) {
super(attrs)
}
static override __module__ = "panel.models.echarts"
static {
this.prototype.default_view = EChartsView
this.define<ECharts.Props>(({Any, Str}) => ({
data: [ Any, {} ],
options: [ Any, {} ],
event_config: [ Any, {} ],
js_events: [ Any, {} ],
theme: [ Str, "default"],
renderer: [ Str, "canvas"],
}))
}
}