@dschz/solid-uplot
Version:
SolidJS wrapper for uPlot — ultra-fast, tiny time-series & charting library
161 lines (155 loc) • 4.08 kB
JSX
import {
getCursorData,
getSeriesData
} from "../chunk/X3NAOFDO.jsx";
// src/createPluginBus.tsx
import { createStore } from "solid-js/store";
var createPluginBus = (initialData = {}) => {
const [data, setData] = createStore(initialData);
return { data, setData };
};
// src/SolidUplot.tsx
import "uplot/dist/uPlot.min.css";
import { mergeRefs } from "@solid-primitives/refs";
import {
createEffect,
createMemo,
createUniqueId,
mergeProps,
onCleanup,
splitProps,
untrack
} from "solid-js";
import uPlot2 from "uplot";
// src/utils/getNewCalendarDayIndices.ts
import "uplot";
// src/eventPlugins.ts
var createCursorMovePlugin = (onCursorMove) => {
return {
hooks: {
setCursor: (u) => {
const cursor = getCursorData(u);
if (!cursor) return;
onCursorMove?.({ u, cursor, seriesData: getSeriesData(u) });
}
}
};
};
// src/SolidUplot.tsx
var SolidUplot = (props) => {
let container;
const _props = mergeProps(
{
id: createUniqueId(),
childrenPlacement: "top",
width: 600,
height: 300,
autoResize: false,
data: [],
resetScales: true,
plugins: [],
legend: {
show: false
}
},
props
);
const [local, options] = splitProps(_props, [
"children",
"childrenPlacement",
"class",
"autoResize",
"onCreate",
"onCursorMove",
"style",
"ref"
]);
const [updateableOptions, newChartOptions] = splitProps(options, [
"data",
"width",
"height",
"resetScales"
]);
const [system, chartOptions] = splitProps(newChartOptions, ["pluginBus", "plugins"]);
const size = () => ({ width: updateableOptions.width, height: updateableOptions.height });
const chartPlugins = createMemo(() => {
const plugins = system.plugins.map(
(plugin) => typeof plugin === "function" ? plugin({ bus: system.pluginBus }) : plugin
);
if (local.onCursorMove) {
plugins.push(createCursorMovePlugin(local.onCursorMove));
}
return plugins;
});
createEffect(() => {
const getInitialSize = () => {
if (local.autoResize) {
const rect = container.getBoundingClientRect();
return {
width: rect.width > 0 ? Math.floor(rect.width) : 600,
height: rect.height > 0 ? Math.floor(rect.height) : 300
};
}
return untrack(size);
};
const initialSize = getInitialSize();
const initialData = untrack(() => updateableOptions.data);
const chart = new uPlot2(
{
...chartOptions,
...initialSize,
plugins: chartPlugins()
},
initialData,
container
);
local.onCreate?.(chart, { seriesData: getSeriesData(chart) });
createEffect(() => {
if (local.autoResize) return;
chart.setSize(size());
});
createEffect(() => {
if (!local.autoResize) return;
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
chart.setSize({ width: Math.floor(width), height: Math.floor(height) });
}
});
resizeObserver.observe(container);
onCleanup(() => {
resizeObserver.disconnect();
});
});
createEffect(() => {
chart.setData(updateableOptions.data, updateableOptions.resetScales);
});
onCleanup(() => {
chart.destroy();
});
});
const classes = () => local.class ? `solid-uplot ${local.class}` : "solid-uplot";
return <div
id="solid-uplot-root"
ref={mergeRefs(local.ref, (el) => container = el)}
class={classes()}
style={{
display: "flex",
"flex-direction": local.childrenPlacement === "top" ? "column" : "column-reverse",
// When autoResize is enabled, fill the parent container
...local.autoResize && {
width: "100%",
height: "100%",
"min-width": "0",
"min-height": "0"
},
...local.style
}}
>
{local.children}
</div>;
};
export {
SolidUplot,
createPluginBus
};