I have a use case for a brush that can be initialized with some state, more like a controlled component rather than an uncontrolled component (as it currently maintains it's own state).
For example on initial render there would already be a brushed area that the user can then drag to resize, rather than always starting from an un-brushed state.
I think this could be achieved by optionally passing in brush state rather than the brush managing it's own state. Is there appetite to support this use-case? I'm happy to submit a PR if so.
Hey @hellosmithy 馃憢 thanks for the suggestion, I think there's definitely a use case for this!
If not too complex to implement, it seems like we could have a dual controlled/uncontrolled component where you can optionally pass in the brush state as you say, but if you don't it will manage it on its own as it does now.
Happy to review a PR or discuss implementation details more! 馃檶
we could have a dual controlled/uncontrolled component where you can optionally pass in the brush state
Yea that's my thoughts too. OK - I'll put together a PR then for you to review.
I was looking for a way to control the Brush component by giving it a brushPosition props. Here's my solution :
import React, { useEffect, useState } from "react";
import { Brush } from "@visx/brush";
const positionToKey = ({ start, end }) => `${start.x},${start.y},${end.x},${end.y}`;
const ControlledBrush = ({ brushPosition, domainToPosition, ...brushProps }) => {
const [innerPosition, setInnerPosition] = useState(brushPosition);
const [key, setKey] = useState(positionToKey(brushPosition));
const { onChange } = brushProps;
useEffect(() => {
if (positionToKey(innerPosition) !== positionToKey(brushPosition)) {
setKey(positionToKey(brushPosition));
}
}, [innerPosition, brushPosition]);
return (
<Brush
key={key}
{...brushProps}
initialBrushPosition={brushPosition}
onChange={(domain) => {
if (domain !== null) {
setInnerPosition(domainToPosition(domain));
}
return onChange && onChange(domain);
}}
/>
);
};
export default ControlledBrush;
The key props change only when an external change to brushPosition is detected. This make it compatible with brush, move & resize interactions.
You have to specify the domainToPosition props witch is a function used to convert domain ({x0, x1, y0, y1}) into position ({start: {x, y}, end:{x, y}}). There's probably a better way to handle this part.
Most helpful comment
Hey @hellosmithy 馃憢 thanks for the suggestion, I think there's definitely a use case for this!
If not too complex to implement, it seems like we could have a dual controlled/uncontrolled component where you can optionally pass in the brush state as you say, but if you don't it will manage it on its own as it does now.
Happy to review a PR or discuss implementation details more! 馃檶