@@ -2,6 +2,9 @@ import { VegaLite } from "react-vega";
22
33import { type PlotState } from "@/lib/types/state/component" ;
44import { type ComponentChangeHandler } from "@/lib/types/state/event" ;
5+ import type { TopLevelParameter } from "vega-lite/src/spec/toplevel" ;
6+ import type { TopLevelSelectionParameter } from "vega-lite/src/selection" ;
7+ import type { Stream } from "vega-typings/types/spec/stream" ;
58
69export interface PlotProps extends Omit < PlotState , "type" > {
710 onChange : ComponentChangeHandler ;
@@ -11,8 +14,38 @@ export function Plot({ id, style, chart, onChange }: PlotProps) {
1114 if ( ! chart ) {
1215 return < div id = { id } style = { style } /> ;
1316 }
17+
18+ function isTopLevelSelectionParameter (
19+ param : TopLevelParameter ,
20+ ) : param is TopLevelSelectionParameter {
21+ return "select" in param ;
22+ }
23+
24+ function isString ( signal_name : string | Stream ) : signal_name is string {
25+ return typeof signal_name === "string" ;
26+ }
27+
28+ const signals : { [ key : string ] : string } = { } ;
29+
30+ chart . params ?. forEach ( ( param ) => {
31+ if ( isTopLevelSelectionParameter ( param ) ) {
32+ if (
33+ typeof param . select === "object" &&
34+ "on" in param . select &&
35+ param . select . on != null
36+ ) {
37+ const signal_name = param . select . on ;
38+ if ( isString ( signal_name ) ) {
39+ signals [ signal_name ] = param . name ;
40+ }
41+ }
42+ }
43+ } ) ;
44+
1445 const { datasets, ...spec } = chart ;
15- const handleSignal = ( _signalName : string , value : unknown ) => {
46+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
47+ // @ts -expect-error
48+ const handleClickSignal = ( signalName : string , value : unknown ) => {
1649 if ( id ) {
1750 return onChange ( {
1851 componentType : "Plot" ,
@@ -22,12 +55,37 @@ export function Plot({ id, style, chart, onChange }: PlotProps) {
2255 } ) ;
2356 }
2457 } ;
58+
59+ type SignalHandler = ( signalName : string , value : unknown ) => void ;
60+
61+ // Currently, we only have click events support, but if more are required, they can be implemented and added in the map below.
62+ const signalHandlerMap : { [ key : string ] : SignalHandler } = {
63+ click : handleClickSignal ,
64+ } ;
65+
66+ const createSignalListeners = ( signals : { [ key : string ] : string } ) => {
67+ const signalListeners : { [ key : string ] : SignalHandler } = { } ;
68+ Object . entries ( signals ) . forEach ( ( [ event , signalName ] ) => {
69+ if ( signalHandlerMap [ event ] ) {
70+ signalListeners [ signalName ] = signalHandlerMap [ event ] ;
71+ } else {
72+ console . warn (
73+ "The signal " + event + " is not yet supported in chartlets.js" ,
74+ ) ;
75+ }
76+ } ) ;
77+
78+ return signalListeners ;
79+ } ;
80+
81+ const signalListeners = createSignalListeners ( signals ) ;
82+
2583 return (
2684 < VegaLite
2785 spec = { spec }
2886 data = { datasets }
2987 style = { style }
30- signalListeners = { { onClick : handleSignal } }
88+ signalListeners = { signalListeners }
3189 actions = { false }
3290 />
3391 ) ;
0 commit comments