Skip to content

Commit 4de65d0

Browse files
authored
Revert "Fix vega warnings (#37)"
This reverts commit 0ae91f1.
1 parent 0ae91f1 commit 4de65d0

File tree

9 files changed

+26
-193
lines changed

9 files changed

+26
-193
lines changed

chartlets.js/src/lib/components/Plot.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,32 @@ import { VegaLite } from "react-vega";
22

33
import { type PlotState } from "@/lib/types/state/component";
44
import { type ComponentChangeHandler } from "@/lib/types/state/event";
5-
import { useSignalListeners } from "@/lib/hooks";
65

76
export interface PlotProps extends Omit<PlotState, "type"> {
87
onChange: ComponentChangeHandler;
98
}
109

1110
export function Plot({ id, style, chart, onChange }: PlotProps) {
12-
const signalListeners = useSignalListeners(chart, id, onChange);
13-
1411
if (!chart) {
1512
return <div id={id} style={style} />;
1613
}
17-
14+
const { datasets, ...spec } = chart;
15+
const handleSignal = (_signalName: string, value: unknown) => {
16+
if (id) {
17+
return onChange({
18+
componentType: "Plot",
19+
id: id,
20+
property: "points",
21+
value: value,
22+
});
23+
}
24+
};
1825
return (
1926
<VegaLite
20-
spec={chart}
27+
spec={spec}
28+
data={datasets}
2129
style={style}
22-
signalListeners={signalListeners}
30+
signalListeners={{ onClick: handleSignal }}
2331
actions={false}
2432
/>
2533
);

chartlets.js/src/lib/components/Select.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
type SelectState,
99
} from "@/lib/types/state/component";
1010
import { type ComponentChangeHandler } from "@/lib/types/state/event";
11-
import { isString } from "@/lib/utils/isString";
1211

1312
export interface SelectProps extends Omit<SelectState, "type"> {
1413
onChange: ComponentChangeHandler;
@@ -65,7 +64,7 @@ export function Select({
6564
function normalizeSelectOption(
6665
option: SelectOption,
6766
): [string | number, string] {
68-
if (isString(option)) {
67+
if (typeof option === "string") {
6968
return [option, option];
7069
} else if (typeof option === "number") {
7170
return [option, option.toString()];

chartlets.js/src/lib/hooks.ts

Lines changed: 1 addition & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import type { StoreState } from "@/lib/types/state/store";
22
import { store } from "@/lib/store";
3-
import { useCallback, useMemo } from "react";
3+
import { useMemo } from "react";
44
import type { ContributionState } from "@/lib/types/state/contribution";
5-
import {
6-
isTopLevelSelectionParameter,
7-
type SignalHandler,
8-
} from "@/lib/types/state/vega";
9-
import type { TopLevelSpec } from "vega-lite/src/spec";
10-
import { isString } from "@/lib/utils/isString";
115
import type {
126
ComponentChangeEvent,
137
ComponentChangeHandler,
@@ -44,104 +38,6 @@ export function makeContributionsHook<S extends object = object>(
4438
};
4539
}
4640

47-
export function useSignalListeners(
48-
chart: TopLevelSpec | null,
49-
id: string | undefined,
50-
onChange: ComponentChangeHandler,
51-
): { [key: string]: SignalHandler } {
52-
/*
53-
Here, we loop through all the params to create map of signals which will
54-
be then used to create the map of signal-listeners because not all
55-
params are event-listeners, and we need to identify them. Later in the
56-
code, we then see which handlers do we have so that we can create
57-
those listeners with the `name` specified in the event-listener object.
58-
*/
59-
const signals: { [key: string]: string } = useMemo(() => {
60-
if (!chart) return {};
61-
const tempSignals: { [key: string]: string } = {};
62-
chart.params?.forEach((param) => {
63-
if (isTopLevelSelectionParameter(param)) {
64-
if (
65-
typeof param.select === "object" &&
66-
"on" in param.select &&
67-
param.select.on != null
68-
) {
69-
const signalName = param.select.on;
70-
/*
71-
The signal name extracted from the `select.on` property can be
72-
either a string or of Stream type (internal Vega
73-
type). But since we create the selection events in
74-
Altair (in the server) using `on="click"` etc., the event type
75-
will be a string, but we need this type-guard to be sure.
76-
If it is a Stream object, that case is not handled yet.
77-
*/
78-
if (isString(signalName)) {
79-
tempSignals[signalName] = param.name;
80-
} else {
81-
console.warn(
82-
`The signal ${param} is of Stream type` +
83-
" (internal Vega-lite type) which is not handled yet.",
84-
);
85-
}
86-
}
87-
}
88-
});
89-
return tempSignals;
90-
}, [chart]);
91-
92-
const handleClickSignal = useCallback(
93-
(signalName: string, signalValue: unknown) => {
94-
if (id) {
95-
return onChange({
96-
componentType: "Plot",
97-
id: id,
98-
property: signalName,
99-
value: signalValue,
100-
});
101-
}
102-
},
103-
[id, onChange],
104-
);
105-
106-
/*
107-
Currently, we only have click events support, but if more are required,
108-
they can be implemented and added in the map below.
109-
*/
110-
const signalHandlerMap: { [key: string]: SignalHandler } = useMemo(
111-
() => ({
112-
click: handleClickSignal,
113-
}),
114-
[handleClickSignal],
115-
);
116-
117-
/*
118-
This function creates the map of signal listeners based on the `signals`
119-
map computed above.
120-
*/
121-
const createSignalListeners = useCallback(
122-
(signals: { [key: string]: string }) => {
123-
const signalListeners: { [key: string]: SignalHandler } = {};
124-
Object.entries(signals).forEach(([event, signalName]) => {
125-
if (signalHandlerMap[event]) {
126-
signalListeners[signalName] = signalHandlerMap[event];
127-
} else {
128-
console.warn(
129-
"The signal " + event + " is not yet supported in chartlets.js",
130-
);
131-
}
132-
});
133-
134-
return signalListeners;
135-
},
136-
[signalHandlerMap],
137-
);
138-
139-
return useMemo(
140-
() => createSignalListeners(signals),
141-
[createSignalListeners, signals],
142-
);
143-
}
144-
14541
/**
14642
* A hook that retrieves the contributions for the given contribution
14743
* point given by `contribPoint`.

chartlets.js/src/lib/types/state/component.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { type CSSProperties } from "react";
2+
import type { VisualizationSpec } from "react-vega";
23
import { isObject } from "@/lib/utils/isObject";
3-
import type { TopLevelSpec } from "vega-lite/src/spec";
4-
import { isString } from "@/lib/utils/isString";
54

65
export type ComponentType =
76
| "Box"
@@ -55,7 +54,9 @@ export interface CheckboxState extends ComponentState {
5554
export interface PlotState extends ComponentState {
5655
type: "Plot";
5756
chart:
58-
| TopLevelSpec // This is the vega-lite specification type
57+
| (VisualizationSpec & {
58+
datasets?: Record<string, unknown>; // Add the datasets property
59+
})
5960
| null;
6061
}
6162

@@ -68,7 +69,7 @@ export interface TypographyState extends ContainerState {
6869
}
6970

7071
export function isComponentState(object: unknown): object is ComponentState {
71-
return isObject(object) && isString(object.type);
72+
return isObject(object) && typeof object.type === "string";
7273
}
7374

7475
export function isContainerState(object: unknown): object is ContainerState {

chartlets.js/src/lib/types/state/vega.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

chartlets.js/src/lib/utils/isString.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

chartlets.js/src/lib/utils/objPath.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { isObject } from "@/lib/utils/isObject";
2-
import { isString } from "@/lib/utils/isString";
32

43
export type ObjPath = (string | number)[];
54
export type ObjPathLike = ObjPath | string | number | undefined | null;
@@ -84,7 +83,7 @@ export function normalizeObjPath(pathLike: ObjPathLike): ObjPath {
8483
}
8584

8685
export function formatObjPath(objPath: ObjPathLike): string {
87-
if (isString(objPath)) {
86+
if (typeof objPath === "string") {
8887
return objPath;
8988
} else if (Array.isArray(objPath)) {
9089
return objPath

chartlets.py/my_extension/my_panel_1.py

Lines changed: 3 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
import copy
2-
from types import NoneType
3-
41
import altair as alt
5-
import pandas as pd
62

7-
from chartlets import Component, Input, Output, State
3+
from chartlets import Component, Input, Output
84
from chartlets.components import Plot, Box, Select
95
from chartlets.demo.contribs import Panel
106
from chartlets.demo.context import Context
@@ -64,7 +60,7 @@ def make_figure(ctx: Context, selected_dataset: int = 0) -> alt.Chart:
6460
# Create another parameter to handle the click events and send the data as
6561
# specified in the fields
6662
click_param = alt.selection_point(
67-
on="click", name="points", fields=["x", variable_name]
63+
on="click", name="onClick", fields=["x", variable_name]
6864
)
6965
# Create a chart type using mark_* where * could be any kind of chart
7066
# supported by Vega. We can add properties and parameters as shown below.
@@ -83,45 +79,5 @@ def make_figure(ctx: Context, selected_dataset: int = 0) -> alt.Chart:
8379
.properties(width=290, height=300, title="Vega charts")
8480
.add_params(corner_var, click_param)
8581
)
86-
return chart
87-
88-
89-
@panel.callback(
90-
Input("plot", property="points"), State("plot", "chart"), Output("plot", "chart")
91-
)
92-
def get_click_event_points(ctx: Context, points, plot) -> alt.Chart:
93-
"""
94-
This callback function shows how we can use the event handlers output
95-
(property="points") which was defined in the `make_figure` callback
96-
function as a `on='click'` handler. Here, we access the variables as
97-
defined in the `fields` argument when creating the `click_param` parameter.
9882

99-
Based on the click event, the user can access the point that was clicked.
100-
The function below extracts the points and changes the color of the bar
101-
that was clicked.
102-
103-
"""
104-
if points:
105-
conditions = []
106-
for field, values in points.items():
107-
if field != "vlPoint":
108-
for value in values:
109-
field_type = plot["encoding"].get(field, {}).get("type", "")
110-
if field_type == "nominal":
111-
conditions.append(f"datum.{field} === '{value}'")
112-
else:
113-
conditions.append(f"datum.{field} === {value}")
114-
conditions.append(f"datum.{field} === {repr(value)}")
115-
116-
condition_expr = " && ".join(conditions)
117-
118-
plot["encoding"]["color"] = {
119-
"condition": {
120-
"test": condition_expr,
121-
# Highlight color when the condition is true
122-
"value": "orange",
123-
},
124-
"value": "steelblue", # Default color
125-
}
126-
127-
return alt.Chart.from_dict(plot)
83+
return chart

chartlets.py/my_extension/my_panel_2.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,7 @@ def make_figure(
8383
)
8484
.properties(width=300, height=300, title="Vega charts using Shorthand syntax")
8585
.add_params(selector)
86-
# .interactive() # Using interactive mode will lead to warning
87-
# `WARN Scale bindings are currently only supported for scales with
88-
# unbinned, continuous domains.`
89-
# because it expects both x and y to be continuous scales,
90-
# but we have x as Nominal which leads to this warning.
91-
# This still works where we can only zoom in on the y axis but
92-
# with a warning.
86+
.interactive()
9387
)
9488
return chart
9589

0 commit comments

Comments
 (0)