Other frameworks
rhp is built on Solid, but a chart is just elements on the page, so it can live inside an app built with anything else. The idea is the same everywhere:
- Give rhp an empty element to draw into.
- Keep the chart’s data in a Solid signal, and set it when your app’s data changes.
- Clean up when the component goes away.
Your app’s JSX belongs to your framework, so the rows are written with Solid’s html template, as in a plain HTML page.
For React there’s a package that does the rest; for other frameworks, @bezda/rhp/standalone has rhp, Solid and html in one import.
React
@bezda/rhp-react turns an rhp chart into a React component:
npm install @bezda/rhp-react
import { useState } from "react";
import { toReact, Chart, Plot, Bar, Label, html } from "@bezda/rhp-react";
const row = (d) => html`
<div>
<${Label} edge="start">${() => d.fruit}<//>
<${Bar} to=${() => d.sold} />
<${Label} at=${() => d.sold}>${() => d.sold}<//>
</div>`;
const FruitChart = toReact((props) => html`
<${Chart} scale=${[0, 30]}>
<${Plot} fruit=${() => props.fruit} sold=${() => props.sold}>${row}<//>
<//>`);
export function App() {
const [sold, setSold] = useState([12, 18, 7]);
return <FruitChart fruit={["Apples", "Bananas", "Cherries"]} sold={sold} className="card" />;
}
propsholds the component’s props. Read them inside functions,${() => props.sold}, so the chart follows them.- A change updates only what it touches: a new number in
soldmoves one bar, as in a Solid app. - The component renders a
<div>that the chart draws into;classNameandstylego on it. - Everything else (the blocks,
slat, the helpers,html,createSignal) comes from the same package.
Vue
npm install @bezda/rhp
<script setup>
import { onMounted, onBeforeUnmount, ref, watch } from "vue";
import { Chart, Plot, Bar, html, render, createSignal } from "@bezda/rhp/standalone";
const props = defineProps(["fruit", "sold"]);
const box = ref(null);
const [data, setData] = createSignal({ fruit: props.fruit, sold: props.sold });
let dispose;
onMounted(() => {
const row = (d) => html`<div><${Bar} to=${() => d.sold} /></div>`;
dispose = render(() => html`
<${Chart} scale=${[0, 30]}>
<${Plot} fruit=${() => data().fruit} sold=${() => data().sold}>${row}<//>
<//>`, box.value);
});
watch(() => [props.fruit, props.sold], ([fruit, sold]) => setData({ fruit, sold }));
onBeforeUnmount(() => dispose?.());
</script>
<template><div ref="box" /></template>
Svelte, Angular and others
The same three steps apply: draw with render into an element once it’s on the page, set the signal when your data changes, and call the function render returns when the component is removed.