PromucFlow_constructor/app/client/src/utils/autoLayout/heightUpdateUtils.ts
Preet Sidhu b7e2cee6c8
feat: Expand auto height implementation to handle auto height use cases. (#22974)
## 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>
2023-05-11 10:15:14 +05:30

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