## Description Expand auto layout implementation to handle auto height use cases. Use cases handled in this PR: 1. Change canvas and container-like widget height on adding / removing widgets. 2. Container height update on content change of individual props, e.g. text, checkbox groups. 3. Tabs widget use cases - change height on tab change, shouldShowProps update. 4. Correct modal widget height. 5. List widget updates - disable auto height, enable manual resizing of item container. 6. Fix resize loop. Fixes https://github.com/appsmithorg/appsmith/issues/21977 Fixes https://github.com/appsmithorg/appsmith/issues/22093 Fixes https://github.com/appsmithorg/appsmith/issues/21837 Fixes https://github.com/appsmithorg/appsmith/issues/22183 Fixes https://github.com/appsmithorg/appsmith/issues/21758 Fixes https://github.com/appsmithorg/appsmith/issues/21870 Fixes https://github.com/appsmithorg/appsmith/issues/22086 Fixes https://github.com/appsmithorg/appsmith/issues/22539 Fixes https://github.com/appsmithorg/appsmith/issues/22329 Fixes #22588 ## Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) ## How Has This Been Tested? - Manual - Jest - Cypress ## Checklist: ### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag --------- Co-authored-by: Aswath K <aswath@appsmith.com> Co-authored-by: rahulramesha <rahul@appsmith.com> Co-authored-by: Aswath K <aswath.sana@gmail.com> Co-authored-by: Ashok Kumar M <35134347+marks0351@users.noreply.github.com>
159 lines
4.8 KiB
TypeScript
159 lines
4.8 KiB
TypeScript
import {
|
|
GridDefaults,
|
|
MAIN_CONTAINER_WIDGET_ID,
|
|
} from "constants/WidgetConstants";
|
|
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
|
|
import type { FlattenedWidgetProps } from "widgets/constants";
|
|
import {
|
|
getTopRow,
|
|
getWidgetMinMaxDimensionsInPixel,
|
|
setDimensions,
|
|
} from "./flexWidgetUtils";
|
|
|
|
/**
|
|
* Determine whether the parent height should be updated or not.
|
|
* 1. Update if computed height of all children is not equal to parent height.
|
|
* 2. Do not update if the widget is a list item container.
|
|
* @param widget | FlattenedWidgetProps : Current widget.
|
|
* @param widgets | CanvasWidgetsReduxState : All widgets.
|
|
* @param parentHeight | number : Current height of the widget.
|
|
* @param computedHeight | number : Min height required to render all children.
|
|
* @param mainCanvasWidth | number : Width of the main canvas.
|
|
* @returns boolean
|
|
*/
|
|
export function shouldUpdateParentHeight(
|
|
widgets: CanvasWidgetsReduxState,
|
|
widget: FlattenedWidgetProps,
|
|
computedHeight: number,
|
|
parentHeight: number,
|
|
): boolean {
|
|
if (
|
|
widget?.isListItemContainer ||
|
|
(widget.parentId && widgets[widget.parentId].type === "LIST_WIDGET_V2") ||
|
|
widget.type === "LIST_WIDGET_V2"
|
|
)
|
|
return false;
|
|
|
|
return computedHeight !== parentHeight;
|
|
}
|
|
|
|
/**
|
|
* Compute total height required by the canvas.
|
|
* @param parent | FlattenedWidgetProps : Parent widget.
|
|
* @param computedHeight | number : Min height required to render all children.
|
|
* @returns number
|
|
*/
|
|
export function getComputedHeight(
|
|
parent: FlattenedWidgetProps,
|
|
widgets: CanvasWidgetsReduxState,
|
|
computedHeight: number,
|
|
mainCanvasWidth: number,
|
|
): number {
|
|
let res: number = computedHeight;
|
|
/**
|
|
* add padding buffer for canvas.
|
|
* if parentRowSpace === 1, => type === CANVAS_WIDGET
|
|
*/
|
|
if (parent.type === "CANVAS_WIDGET")
|
|
res +=
|
|
parent.widgetId === MAIN_CONTAINER_WIDGET_ID
|
|
? GridDefaults.MAIN_CANVAS_EXTENSION_OFFSET
|
|
: 2;
|
|
|
|
/**
|
|
* If widget is a Tabs widget, and tabs are visible,
|
|
* add 4 rows to the height to accommodate the tab header.
|
|
*/
|
|
if (parent.type === "TABS_WIDGET" && parent?.shouldShowTabs) res += 4;
|
|
|
|
const minHeight: number =
|
|
parent.widgetId !== MAIN_CONTAINER_WIDGET_ID
|
|
? (getWidgetMinMaxDimensionsInPixel(parent, mainCanvasWidth)?.minHeight ||
|
|
0) / GridDefaults.DEFAULT_GRID_ROW_HEIGHT
|
|
: (parent.minHeight || 0) / GridDefaults.DEFAULT_GRID_ROW_HEIGHT;
|
|
/**
|
|
* If the widget is a canvas widget and it's parent is not the main container,
|
|
* then we need to check the parent's minHeight as well.
|
|
* e.g. an empty canvas may require only 5 rows.
|
|
* However a tab widget requires a min of 30 rows. So the child canvas must comply.
|
|
*/
|
|
let containerMinHeight = 0;
|
|
if (
|
|
parent.type === "CANVAS_WIDGET" &&
|
|
parent.parentId &&
|
|
parent.parentId !== MAIN_CONTAINER_WIDGET_ID
|
|
) {
|
|
const container = widgets[parent.parentId];
|
|
containerMinHeight =
|
|
(getWidgetMinMaxDimensionsInPixel(container, mainCanvasWidth)
|
|
?.minHeight || 0) / GridDefaults.DEFAULT_GRID_ROW_HEIGHT;
|
|
if (container.type === "TABS_WIDGET" && container?.shouldShowTabs)
|
|
containerMinHeight -= 4;
|
|
}
|
|
res = Math.max(res, minHeight, containerMinHeight);
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Set the new height of the parent widget.
|
|
* @param parent | FlattenedWidgetProps : Parent widget.
|
|
* @param height | number : Height to be set.
|
|
* @param modalHeight | number : Height of the modal.
|
|
* @param isMobile | boolean : Is mobile viewport.
|
|
* @returns FlattenedWidgetProps
|
|
*/
|
|
export function updateParentHeight(
|
|
parent: FlattenedWidgetProps,
|
|
height: number,
|
|
modalHeight: number,
|
|
isMobile = false,
|
|
): FlattenedWidgetProps {
|
|
const parentTopRow: number = getTopRow(parent, isMobile);
|
|
let updatedParent = setDimensions(
|
|
parent,
|
|
parentTopRow,
|
|
parentTopRow + height,
|
|
null,
|
|
null,
|
|
isMobile,
|
|
);
|
|
/**
|
|
* For Modal widget, set additional height property
|
|
*/
|
|
if (parent.type === "MODAL_WIDGET") {
|
|
// Add a couple of pixels to the modal height to avoid scrollbars.
|
|
const bufferForModal = 2;
|
|
updatedParent = {
|
|
...updatedParent,
|
|
height: modalHeight + bufferForModal,
|
|
};
|
|
}
|
|
return updatedParent;
|
|
}
|
|
|
|
/**
|
|
* Get height of modal widget. => rows * rowSpace
|
|
* @param parent | FlattenedWidgetProps
|
|
* @param computedHeight | number
|
|
* @param divisor | number
|
|
* @returns number
|
|
*/
|
|
export function getModalHeight(
|
|
parent: FlattenedWidgetProps,
|
|
computedHeight: number,
|
|
divisor: number,
|
|
): number {
|
|
let res: number = computedHeight;
|
|
// if (parent.parentRowSpace === 1) res -= 2;
|
|
res *= divisor;
|
|
if (parent.type === "MODAL_WIDGET")
|
|
res *= divisor === 1 ? GridDefaults.DEFAULT_GRID_ROW_HEIGHT : 1;
|
|
return res;
|
|
}
|
|
|
|
export function getDivisor(widget: FlattenedWidgetProps): number {
|
|
return widget.type === "CANVAS_WIDGET"
|
|
? GridDefaults.DEFAULT_GRID_ROW_HEIGHT
|
|
: 1;
|
|
}
|