Param Panel

Dependent Ranges

Change one control's valid range in response to another, using atomic configure() to avoid ever passing through an invalid state.

A control's valid range can depend on the value of another control. Here, the maximum a threshold slider can reach depends on the selected bitDepth. This is a case where configure() being atomic really matters — the range and the (possibly clamped) value are applied together, so threshold never briefly holds a value above its new max.

Source

const bitDepth = pp.select({
  label: "Bit depth",
  value: 8,
  options: [
    { label: "8-bit", value: 8 },
    { label: "10-bit", value: 10 },
    { label: "12-bit", value: 12 },
  ],
});

const threshold = pp.slider({
  label: "Threshold",
  value: 128,
  min: 0,
  max: 255,
  step: 1,
});

bitDepth.subscribe((depth, details) => {
  const max = 2 ** depth - 1;
  const current = threshold.get();

  // New max and clamped value applied together — never invalid in between.
  threshold.configure({
    max,
    value: Math.min(current, max),
  });

  if (details.final) {
    rebuildProcessingPipeline();
  }
});

Notable details

  • Switching bitDepth from 12-bit (max = 4095) to 8-bit (max = 255) while threshold sits at 1000 would be invalid if max and value were set separately — threshold.configure({ max: 255 }) alone would momentarily leave the control at a value above its new maximum. Passing both fields in the same configure() call means validation happens against the whole proposed configuration before anything is applied.
  • bitDepth's own subscriber uses details.final to gate rebuildProcessingPipeline(), the same intermediate/final pattern used throughout the library.

On this page