Packages
kino
0.5.0
0.19.0
0.18.0
0.17.0
0.16.1
0.16.0
0.15.3
0.15.2
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.2
0.13.1
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.1
0.8.0
0.7.0
0.6.2
0.6.1
0.6.0
retired
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Interactive widgets for Livebook
Current section
Files
Jump to
Current section
Files
lib/assets/vega_lite/main.js
import "https://cdn.jsdelivr.net/npm/vega@5.21.0";
import "https://cdn.jsdelivr.net/npm/vega-lite@5.2.0";
import "https://cdn.jsdelivr.net/npm/vega-embed@6.20.2";
// See https://github.com/vega/vega-lite/blob/b61b13c2cbd4ecde0448544aff6cdaea721fd22a/src/compile/data/assemble.ts#L228-L231
const DEFAULT_DATASET_NAME = "source_0";
const throttledResize = throttle((view) => view.resize(), 1_000);
export function init(ctx, data) {
const { spec, datasets } = data;
if (!spec.data) {
spec.data = { values: [] };
}
vegaEmbed(ctx.root, spec, {})
.then((result) => {
const view = result.view;
datasets.forEach(([dataset, data]) => {
view.resize();
view.data(dataset || DEFAULT_DATASET_NAME, data).run();
});
ctx.handleEvent("push", ({ data, dataset, window }) => {
dataset = dataset || DEFAULT_DATASET_NAME;
const currentData = view.data(dataset);
const changeset = buildChangeset(currentData, data, window);
// Schedule resize after the run finishes
throttledResize(view);
view.change(dataset, changeset).run();
});
})
.catch((error) => {
const message = `Failed to render the given Vega-Lite specification, got the following error:\n\n ${error.message}\n\nMake sure to check for typos.`;
ctx.root.innerHTML = `
<div style="color: #FF3E38; white-space: pre-wrap;">${message}</div>
`;
});
};
function buildChangeset(currentData, newData, window) {
if (window === 0) {
return vega.changeset().remove(currentData);
} else if (window) {
const toInsert = newData.slice(-window);
const freeSpace = Math.max(window - toInsert.length, 0);
const toRemove = currentData.slice(0, -freeSpace);
return vega.changeset().remove(toRemove).insert(toInsert);
} else {
return vega.changeset().insert(newData);
}
}
/**
* A simple throttle version that ensures the given function
* is called at most once within the given time window.
*/
export function throttle(fn, windowMs) {
let ignore = false;
return (...args) => {
if (!ignore) {
fn(...args);
ignore = true;
setTimeout(() => {
ignore = false;
}, windowMs);
}
};
}