leva icon indicating copy to clipboard operation
leva copied to clipboard

Feature Request: Reactive constants inside control panel derived from inputs

Open Amar-Gill opened this issue 1 year ago • 5 comments

I think it would be nice to display a reactive value derived from the values in the control panel itself. It can leverage the get hook used in the render option already.

Of course I can take the values and display the computed value in a div somewhere, but it would be nice to contain the computed value to the control panel since the values are related.

Technically it's not an input, more like an embellishment to the control panel.

Example:

const { width, height, depth, volume } = useControls({
  width: {
    value: 1,
    min: 1,
    max: 10,
    step: 1,
  },
  height: {
    value: 1,
    min: 1,
    max: 6,
    step: 1,
  },
  depth: {
    value: 1,
    min: 1,
    max: 10,
    step: 1,
  },
  volume: {
    derivedValue: (get) => get('width') * get('height') * get('depth'),
  },
});

Amar-Gill avatar Jul 10 '22 00:07 Amar-Gill

found this issue - kind of related: https://github.com/pmndrs/leva/issues/305

Amar-Gill avatar Jul 10 '22 00:07 Amar-Gill

also found this -- https://github.com/pmndrs/leva/issues/112 which is asking almost the same thing.

I can begin to look into making a plug in. Feel free to close this issue if you think it's better served as a plug in vs. an update to api that I proposed above.

Amar-Gill avatar Jul 10 '22 00:07 Amar-Gill

Here's a work around using a disabled input and the set method. Link to repro for the work around: https://stackblitz.com/edit/vitejs-vite-o5b1yc?file=src%2FApp.jsx

  const [w, setW] = useState(1);
  const [h, setH] = useState(1);
  const [d, setD] = useState(1);
  let v = w * h * d;

  const [, set] = useControls(
    () => ({
      width: {
        value: w,
        min: 1,
        max: 10,
        step: 1,
        onChange: (v) => setW(v),
      },
      height: {
        value: h,
        min: 1,
        max: 6,
        step: 1,
        onChange: (v) => setH(v),
      },
      depth: {
        value: d,
        min: 1,
        max: 10,
        step: 1,
        onChange: (v) => setD(v),
      },
      volume: {
        value: v,
        disabled: true,
      },
    }),
    [w, h, d],
  );

  useEffect(() => {
    v = w * h * d;
    set({ volume: v });
  }, [w, h, d]);

Amar-Gill avatar Jul 10 '22 20:07 Amar-Gill

Do you want to attempt a contribution for this?

gsimone avatar Jul 14 '22 09:07 gsimone

Hey if you think it's a valuable feature I will give it a shot @gsimone -- I can find time beginning in September.

Wanted to see if others will find it useful before jumping in.

Amar-Gill avatar Jul 26 '22 13:07 Amar-Gill