export default function ResizableContainer()

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>
  );
}