PromucFlow_constructor/app/client/src/components/editorComponents/ResizableUtils.tsx

155 lines
4.1 KiB
TypeScript

import { CSSProperties } from "react";
import { XYCoord } from "react-dnd";
import { theme } from "constants/DefaultTheme";
import { WidgetProps, WidgetRowCols } from "widgets/BaseWidget";
import { isDropZoneOccupied } from "utils/WidgetPropsUtils";
import { OccupiedSpace } from "constants/editorConstants";
export type UIElementSize = { height: number; width: number };
export const RESIZABLE_CONTAINER_BORDER_THEME_INDEX = 1;
const RESIZE_HANDLE_HOVER_AREA_WIDTH = 12;
export const getHandleSyles = (): {
top: CSSProperties;
bottom: CSSProperties;
right: CSSProperties;
left: CSSProperties;
bottomRight: CSSProperties;
bottomLeft: CSSProperties;
} => {
const hoverWidth = RESIZE_HANDLE_HOVER_AREA_WIDTH;
const hoverWidthHalf = hoverWidth / 2;
const halfBorder =
theme.borders[RESIZABLE_CONTAINER_BORDER_THEME_INDEX].thickness / 2;
const shiftedHoverWidthHalf = hoverWidthHalf + halfBorder;
const hoverCornerWidth = hoverWidth + hoverWidth / 4;
return {
top: {
height: hoverWidth + "px",
top: "-" + shiftedHoverWidthHalf + "px",
zIndex: 1,
cursor: "ns-resize",
},
bottomRight: {
height: hoverCornerWidth + "px",
width: hoverCornerWidth + "px",
zIndex: 1,
cursor: "nwse-resize",
},
bottomLeft: {
height: hoverCornerWidth + "px",
width: hoverCornerWidth + "px",
zIndex: 1,
cursor: "nesw-resize",
},
bottom: {
height: hoverWidth + "px",
bottom: "-" + shiftedHoverWidthHalf + "px",
zIndex: 1,
cursor: "ns-resize",
},
left: {
width: hoverWidth + "px",
left: "-" + shiftedHoverWidthHalf + "px",
zIndex: 1,
cursor: "ew-resize",
},
right: {
width: hoverWidth + "px",
right: "-" + shiftedHoverWidthHalf + "px",
zIndex: 1,
cursor: "ew-resize",
},
};
};
export const computeUpdatedRowCols = (
isColliding: boolean,
delta: UIElementSize,
position: XYCoord,
props: WidgetProps,
): WidgetRowCols | false => {
if (isColliding) return false;
const newRowCols: WidgetRowCols = {
leftColumn: props.leftColumn + position.x / props.parentColumnSpace,
topRow: props.topRow + position.y / props.parentRowSpace,
rightColumn:
props.rightColumn + (delta.width + position.x) / props.parentColumnSpace,
bottomRow:
props.bottomRow + (delta.height + position.y) / props.parentRowSpace,
};
if (
props.leftColumn !== newRowCols.leftColumn ||
props.topRow !== newRowCols.topRow ||
props.bottomRow !== newRowCols.bottomRow ||
props.rightColumn !== newRowCols.rightColumn
) {
return newRowCols;
}
return false;
};
export const hasCollision = (
delta: UIElementSize,
position: XYCoord,
props: WidgetProps,
occupiedSpaces?: OccupiedSpace[],
): boolean => {
const left = props.leftColumn + position.x / props.parentColumnSpace;
const top = props.topRow + position.y / props.parentRowSpace;
const right =
props.rightColumn + (delta.width + position.x) / props.parentColumnSpace;
const bottom =
props.bottomRow + (delta.height + position.y) / props.parentRowSpace;
return isDropZoneOccupied(
{
left,
top,
bottom,
right,
},
props.widgetId,
occupiedSpaces,
);
};
// TODO(abhinav): Memoize this?
export const getBorderStyles = (
isWidgetFocused: boolean,
isColliding: boolean,
padding: number,
): CSSProperties => {
const selectedColor = theme.colors.containerBorder;
const collisionColor = theme.colors.error;
// To fix the widget select/unselect size descripancy: Issue #127
// Always have the border, just toggle the opacity.
const unselectedColor = "transparent";
const borderThickness =
theme.borders[RESIZABLE_CONTAINER_BORDER_THEME_INDEX].thickness + "px";
const borderStyle =
theme.borders[RESIZABLE_CONTAINER_BORDER_THEME_INDEX].style;
let borderColor = unselectedColor;
if (isWidgetFocused) {
borderColor = selectedColor;
}
if (isColliding && isWidgetFocused) {
borderColor = collisionColor;
}
return {
border: [borderThickness, borderStyle, borderColor].join(" "),
padding: padding + "px",
};
};