diff options
Diffstat (limited to 'src/ui/Controls.jsx')
| -rw-r--r-- | src/ui/Controls.jsx | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/ui/Controls.jsx b/src/ui/Controls.jsx new file mode 100644 index 0000000..f999e4f --- /dev/null +++ b/src/ui/Controls.jsx @@ -0,0 +1,171 @@ +/** + * Relabi controls + * @module src/ui/Controls.jsx; + */ + +import * as React from "react"; +import { useCallback, useRef } from "react"; + +import Slider from "rc-slider"; +import TooltipSlider, { handleRender } from "./TooltipSlider.tsx"; +import "rc-slider/assets/index.css"; + +const WAVE_SHAPE_NAMES = ["sine", "triangle", "saw", "square"]; + +export default function Controls({ relabi }) { + /** + * Handle updating a slider + */ + const onChange = useCallback( + (type, index) => (value) => { + if (type === "bound") { + relabi.bounds[index].level = value; + } + if (type === "frequency") { + relabi.waves[index].frequency = Math.exp(value); + } + if (type === "shape") { + relabi.waves[index].shape = WAVE_SHAPE_NAMES[value]; + } + }, + [relabi] + ); + + return ( + <ControlRow> + <ControlBox> + <Label>Bounds</Label> + <SliderRow> + {relabi?.bounds.map((bound, index) => ( + <ControlSlider + rel={`bound_${index}`} + type="bound" + index={index} + onChange={onChange} + min={-1} + max={1} + step={0.01} + defaultValue={bound.level} + color={bound.color} + reverse + /> + ))} + </SliderRow> + </ControlBox> + + <ControlBox> + <Label>Wave speeds</Label> + <SliderRow> + {relabi?.waves.map((wave, index) => ( + <ControlSlider + rel={`frequency_${index}`} + type="frequency" + index={index} + onChange={onChange} + min={-2} + max={3} + step={0.001} + defaultValue={Math.log(wave.frequency)} + color={"#8a8"} + /> + ))} + </SliderRow> + </ControlBox> + + <ControlBox> + <Label>Wave shapes</Label> + <SliderRow> + {relabi?.waves.map((wave, index) => ( + <ControlSlider + rel={`shape_${index}`} + type="shape" + index={index} + onChange={onChange} + min={0} + max={3} + step={1} + defaultValue={WAVE_SHAPE_NAMES.indexOf(wave.shape)} + color={"#998"} + tipFormatter={(value) => WAVE_SHAPE_NAMES[value]} + /> + ))} + </SliderRow> + </ControlBox> + </ControlRow> + ); +} + +/** + * UI Elements + */ +const ControlRow = ({ children }) => ( + <div + style={{ + display: "flex", + flexDirection: "row", + marginTop: "1rem", + }} + > + {children} + </div> +); + +const ControlBox = ({ children }) => ( + <div + style={{ + marginLeft: "1rem", + }} + > + {children} + </div> +); + +const SliderRow = ({ children }) => ( + <div + style={{ + display: "flex", + flexDireciton: "row", + height: "10rem", + marginTop: "0.5rem", + }} + > + {children} + </div> +); + +const Label = ({ children }) => ( + <div style={{ fontSize: "0.75rem" }}>{children}</div> +); + +const ControlSlider = ({ + type, + index, + min, + max, + step, + reverse, + defaultValue, + color, + onChange, + tipFormatter, +}) => ( + <div style={{ marginRight: "0.5rem" }}> + <TooltipSlider + vertical + min={min} + max={max} + step={step} + reverse={reverse} + defaultValue={defaultValue} + onChange={onChange(type, index)} + handleStyle={{ + backgroundColor: color, + borderColor: color, + opacity: 1, + }} + trackStyle={{ backgroundColor: "#888", width: "2px" }} + railStyle={{ backgroundColor: "#888", width: "2px" }} + tipFormatter={tipFormatter || ((value) => value)} + /> + </div> +); |
