in superset-frontend/src/dashboard/components/resizable/ResizableContainer.tsx [152:321]
export default function ResizableContainer({
id,
children,
widthMultiple,
heightMultiple,
staticHeight,
staticHeightMultiple,
staticWidth,
staticWidthMultiple,
onResizeStop,
onResize,
onResizeStart,
editMode,
adjustableWidth = true,
adjustableHeight = true,
gutterWidth = GRID_GUTTER_SIZE,
widthStep = GRID_BASE_UNIT,
heightStep = GRID_BASE_UNIT,
minWidthMultiple = 1,
maxWidthMultiple = proxyToInfinity,
minHeightMultiple = 1,
maxHeightMultiple = proxyToInfinity,
}: ResizableContainerProps) {
const [isResizing, setIsResizing] = useState<boolean>(false);
const handleResize = useCallback<ResizeCallback>(
(event, direction, elementRef, delta) => {
if (onResize) onResize(event, direction, elementRef, delta);
},
[onResize],
);
const handleResizeStart = useCallback<ResizeStartCallback>(
(e, dir, elementRef) => {
if (onResizeStart) onResizeStart(e, dir, elementRef);
setIsResizing(true);
},
[onResizeStart],
);
const handleResizeStop = useCallback<ResizeCallback>(
(event, direction, elementRef, delta) => {
if (onResizeStop) {
const nextWidthMultiple =
widthMultiple + Math.round(delta.width / (widthStep + gutterWidth));
const nextHeightMultiple =
heightMultiple + Math.round(delta.height / heightStep);
onResizeStop(
event,
direction,
elementRef,
{
width: adjustableWidth ? nextWidthMultiple : 0,
height: adjustableHeight ? nextHeightMultiple : 0,
},
// @ts-ignore
id,
);
}
setIsResizing(false);
},
[
onResizeStop,
widthMultiple,
heightMultiple,
widthStep,
heightStep,
gutterWidth,
adjustableWidth,
adjustableHeight,
id,
],
);
const size = useMemo(
() => ({
width: adjustableWidth
? (widthStep + gutterWidth) * widthMultiple - gutterWidth
: (staticWidthMultiple && staticWidthMultiple * widthStep) ||
staticWidth ||
undefined,
height: adjustableHeight
? heightStep * heightMultiple
: (staticHeightMultiple && staticHeightMultiple * heightStep) ||
staticHeight ||
undefined,
}),
[
adjustableWidth,
widthStep,
gutterWidth,
widthMultiple,
staticWidthMultiple,
staticWidth,
adjustableHeight,
heightStep,
heightMultiple,
staticHeightMultiple,
staticHeight,
],
);
const handleComponent = useMemo(
() => ({
right: <RightResizeHandle />,
bottom: <BottomResizeHandle />,
bottomRight: <BottomRightResizeHandle />,
}),
[],
);
const enableConfig = useMemo(() => {
if (editMode && adjustableWidth && adjustableHeight) {
return resizableConfig.widthAndHeight;
}
if (editMode && adjustableWidth) {
return resizableConfig.widthOnly;
}
if (editMode && adjustableHeight) {
return resizableConfig.heightOnly;
}
return resizableConfig.notAdjustable;
}, [editMode, adjustableWidth, adjustableHeight]);
return (
<StyledResizable
enable={enableConfig}
grid={SNAP_TO_GRID}
gridGap={undefined}
minWidth={
adjustableWidth
? minWidthMultiple * (widthStep + gutterWidth) - gutterWidth
: undefined
}
minHeight={adjustableHeight ? minHeightMultiple * heightStep : undefined}
maxWidth={
adjustableWidth && size.width
? Math.max(
size.width,
Math.min(
proxyToInfinity,
maxWidthMultiple * (widthStep + gutterWidth) - gutterWidth,
),
)
: undefined
}
maxHeight={
adjustableHeight && size.height
? Math.max(
size.height,
Math.min(proxyToInfinity, maxHeightMultiple * heightStep),
)
: undefined
}
size={size}
onResizeStart={handleResizeStart}
onResize={handleResize}
onResizeStop={handleResizeStop}
handleComponent={handleComponent}
className={cx(
'resizable-container',
isResizing && 'resizable-container--resizing',
)}
handleClasses={HANDLE_CLASSES}
>
{children}
</StyledResizable>
);
}