JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
CSS
body {
margin: 0;
}
JavaScript
import { html, render, useState, useEffect, useCallback } from "https://unpkg.com/htm/preact/standalone.module.js";
function useVars() {
// a^2 + b^2 + c^2 = 1
const [a, setA] = useState(1);
const [b, setB] = useState(0);
const [c, setC] = useState(0);
return {
a,
b,
c,
setA(a) {
if (a < -1) a = -1;
if (a > 1) a = 1;
setA(a);
const sum = 1 - a ** 2;
setB(sum * b / (b + c));
setC(sum * c / (b + c));
},
setB(b) {
if (b < -1) b = -1;
if (b > 1) b = 1;
setB(b);
const sum = 1 - b ** 2;
setA(sum / 2);
setC(sum / 2);
},
setC(c) {
if (c < -1) c = -1;
if (c > 1) c = 1;
setC(c);
const sum = 1 - c ** 2;
setA(sum / 2);
setB(sum / 2);
}
}
}
function App() {
const { a, b, c, setA, setB, setC } = useVars();
return html`
<div
style=${{
display: "flex",
alignItems: "center",
justifyContent: "space-around",
width: "100vw",
height: "100vh"
}}
>
<${Bar}
color="red"
value=${a}
setValue=${setA}
/>
<${Bar}
color="blue"
value=${b}
setValue=${setB}
/>
<${Bar}
color="purple"
value=${c}
setValue=${setC}
/>
</div>
`;
}
function Bar({ value, setValue, color }) {
const [dragStart, setDragStart] = useState(null);
useCursor(dragStart ? "grabbing" : null);
const onMouseDown = useCallback((event) => {
event.preventDefault();
setDragStart({
mouseY: event.clientY,
value: value
});
}, [value]);
const onMouseMove = useCallback((event) => {
if (dragStart !== null) {
const deltaY = event.clientY - dragStart.mouseY;
let newValue = dragStart.value - 0.005 * deltaY;
setValue(newValue);
}
}, [dragStart, setValue]);
const onMouseUp = useCallback((event) => {
setDragStart(null);
}, []);
...