From 3f71fa68a1c2c61ab583c3e16fdb2fab19276047 Mon Sep 17 00:00:00 2001 From: Abhinav Jha Date: Mon, 14 Nov 2022 09:49:25 +0530 Subject: [PATCH] feat: Auto-height add reducers and actions (#17953) * Add reducers for auto height feature (Internal Change, No changes reflected to users) Co-authored-by: ankurrsinghal --- app/client/src/actions/autoHeightActions.ts | 52 +++++++ app/client/src/actions/controlActions.tsx | 10 ++ .../src/ce/constants/ReduxActionConstants.tsx | 7 + app/client/src/ce/reducers/index.tsx | 4 + .../EditorContextProvider.tsx | 14 ++ app/client/src/pages/AppViewer/index.tsx | 14 ++ .../autoHeightLayoutTreeReducer.test.ts | 99 +++++++++++++ .../autoHeightLayoutTreeReducer.ts | 56 ++++++++ .../canvasLevelsReducer.test.ts | 44 ++++++ .../autoHeightReducers/canvasLevelsReducer.ts | 29 ++++ .../canvasWidgetsReducer.test.ts | 135 ++++++++++++++++++ .../entityReducers/canvasWidgetsReducer.tsx | 35 ++++- .../src/reducers/entityReducers/index.ts | 4 + app/client/src/utils/autoHeight/constants.ts | 8 ++ 14 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 app/client/src/actions/autoHeightActions.ts create mode 100644 app/client/src/reducers/entityReducers/autoHeightReducers/autoHeightLayoutTreeReducer.test.ts create mode 100644 app/client/src/reducers/entityReducers/autoHeightReducers/autoHeightLayoutTreeReducer.ts create mode 100644 app/client/src/reducers/entityReducers/autoHeightReducers/canvasLevelsReducer.test.ts create mode 100644 app/client/src/reducers/entityReducers/autoHeightReducers/canvasLevelsReducer.ts create mode 100644 app/client/src/reducers/entityReducers/canvasWidgetsReducer.test.ts create mode 100644 app/client/src/utils/autoHeight/constants.ts diff --git a/app/client/src/actions/autoHeightActions.ts b/app/client/src/actions/autoHeightActions.ts new file mode 100644 index 0000000000..50cdca16ed --- /dev/null +++ b/app/client/src/actions/autoHeightActions.ts @@ -0,0 +1,52 @@ +import { + ReduxActionTypes, + ReduxAction, +} from "@appsmith/constants/ReduxActionConstants"; +import { TreeNode } from "utils/autoHeight/constants"; + +export interface UpdateWidgetAutoHeightPayload { + widgetId: string; + height: number; +} + +export function setAutoHeightLayoutTreeAction( + tree: Record, + canvasLevelMap: Record, +) { + return { + type: ReduxActionTypes.SET_AUTO_HEIGHT_LAYOUT_TREE, + payload: { tree, canvasLevelMap }, + }; +} + +export function generateAutoHeightLayoutTreeAction( + shouldCheckContainersForDynamicHeightUpdates: boolean, + layoutUpdated?: boolean, +) { + return { + type: ReduxActionTypes.GENERATE_AUTO_HEIGHT_LAYOUT_TREE, + payload: { + shouldCheckContainersForDynamicHeightUpdates, + layoutUpdated: !!layoutUpdated, + }, + }; +} + +export function updateWidgetAutoHeightAction( + widgetId: string, + height: number, +): ReduxAction { + return { + type: ReduxActionTypes.UPDATE_WIDGET_AUTO_HEIGHT, + payload: { + widgetId, + height, + }, + }; +} + +export function checkContainersForAutoHeightAction() { + return { + type: ReduxActionTypes.CHECK_CONTAINERS_FOR_AUTO_HEIGHT, + }; +} diff --git a/app/client/src/actions/controlActions.tsx b/app/client/src/actions/controlActions.tsx index af5cc316c9..1962f772e7 100644 --- a/app/client/src/actions/controlActions.tsx +++ b/app/client/src/actions/controlActions.tsx @@ -2,6 +2,7 @@ import { ReduxActionTypes, ReduxAction, } from "@appsmith/constants/ReduxActionConstants"; +import { UpdateWidgetsPayload } from "reducers/entityReducers/canvasWidgetsReducer"; import { DynamicPath } from "utils/DynamicBindingUtils"; export const updateWidgetPropertyRequest = ( @@ -74,6 +75,15 @@ export const setWidgetDynamicProperty = ( }; }; +export const updateMultipleWidgetPropertiesAction = ( + widgetsToUpdate: UpdateWidgetsPayload, +) => { + return { + type: ReduxActionTypes.UPDATE_MULTIPLE_WIDGET_PROPERTIES, + payload: widgetsToUpdate, + }; +}; + export interface UpdateWidgetPropertyRequestPayload { widgetId: string; propertyPath: string; diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index 5591309f0d..157cf27a24 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -703,7 +703,14 @@ export const ReduxActionTypes = { SET_JS_PANE_CONFIG_SELECTED_TAB: "SET_JS_PANE_CONFIG_SELECTED_TAB", SET_JS_PANE_RESPONSE_SELECTED_TAB: "SET_JS_PANE_RESPONSE_SELECTED_TAB", SET_JS_PANE_RESPONSE_PANE_HEIGHT: "SET_JS_PANE_RESPONSE_PANE_HEIGHT", + SET_AUTO_HEIGHT_LAYOUT_TREE: "SET_AUTO_HEIGHT_LAYOUT_TREE", + UPDATE_MULTIPLE_WIDGET_PROPERTIES: "UPDATE_MULTIPLE_WIDGET_PROPERTIES", + SET_CANVAS_LEVELS_MAP: "SET_CANVAS_LEVELS_MAP", + GENERATE_AUTO_HEIGHT_LAYOUT_TREE: "GENERATE_AUTO_HEIGHT_LAYOUT_TREE", + CHECK_CONTAINERS_FOR_AUTO_HEIGHT: "CHECK_CONTAINERS_FOR_AUTO_HEIGHT", + UPDATE_WIDGET_AUTO_HEIGHT: "UPDATE_WIDGET_AUTO_HEIGHT", SET_LINT_ERRORS: "SET_LINT_ERRORS", + PROCESS_AUTO_HEIGHT_UPDATES: "PROCESS_AUTO_HEIGHT_UPDATES", }; export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTypes]; diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index 21bb63ba17..d8f1c5d215 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -66,6 +66,8 @@ import tenantReducer, { } from "@appsmith/reducers/tenantReducer"; import { FocusHistoryState } from "reducers/uiReducers/focusHistoryReducer"; import { EditorContextState } from "reducers/uiReducers/editorContextReducer"; +import { AutoHeightLayoutTreeReduxState } from "reducers/entityReducers/autoHeightReducers/autoHeightLayoutTreeReducer"; +import { CanvasLevelsReduxState } from "reducers/entityReducers/autoHeightReducers/canvasLevelsReducer"; import { LintErrors } from "reducers/lintingReducers/lintErrorsReducers"; import lintErrorReducer from "reducers/lintingReducers"; @@ -136,6 +138,8 @@ export interface AppState { meta: MetaState; app: AppDataState; jsActions: JSCollectionDataState; + autoHeightLayoutTree: AutoHeightLayoutTreeReduxState; + canvasLevels: CanvasLevelsReduxState; }; evaluations: { tree: EvaluatedTreeState; diff --git a/app/client/src/components/editorComponents/EditorContextProvider.tsx b/app/client/src/components/editorComponents/EditorContextProvider.tsx index 933941b408..e1b94f2989 100644 --- a/app/client/src/components/editorComponents/EditorContextProvider.tsx +++ b/app/client/src/components/editorComponents/EditorContextProvider.tsx @@ -21,6 +21,10 @@ import { triggerEvalOnMetaUpdate, } from "actions/metaActions"; +import { + checkContainersForAutoHeightAction, + updateWidgetAutoHeightAction, +} from "actions/autoHeightActions"; export type EditorContextType = { executeAction?: (triggerPayload: ExecuteTriggerPayload) => void; updateWidget?: ( @@ -48,6 +52,8 @@ export type EditorContextType = { propertyName: string, propertyValue: any, ) => void; + updateWidgetAutoHeight?: (widgetId: string, height: number) => void; + checkContainersForAutoHeight?: () => void; }; export const EditorContext: Context = createContext({}); @@ -58,6 +64,7 @@ type EditorContextProviderProps = EditorContextType & { function EditorContextProvider(props: EditorContextProviderProps) { const { batchUpdateWidgetProperty, + checkContainersForAutoHeight, children, deleteWidgetProperty, disableDrag, @@ -66,6 +73,7 @@ function EditorContextProvider(props: EditorContextProviderProps) { syncUpdateWidgetMetaProperty, triggerEvalOnMetaUpdate, updateWidget, + updateWidgetAutoHeight, updateWidgetProperty, } = props; @@ -82,6 +90,8 @@ function EditorContextProvider(props: EditorContextProviderProps) { deleteWidgetProperty, batchUpdateWidgetProperty, triggerEvalOnMetaUpdate, + updateWidgetAutoHeight, + checkContainersForAutoHeight, }), [ executeAction, @@ -93,6 +103,8 @@ function EditorContextProvider(props: EditorContextProviderProps) { deleteWidgetProperty, batchUpdateWidgetProperty, triggerEvalOnMetaUpdate, + updateWidgetAutoHeight, + checkContainersForAutoHeight, ], ); return ( @@ -121,6 +133,8 @@ const mapDispatchToProps = { deleteWidgetProperty: deletePropertyAction, batchUpdateWidgetProperty: batchUpdatePropertyAction, triggerEvalOnMetaUpdate: triggerEvalOnMetaUpdate, + updateWidgetAutoHeight: updateWidgetAutoHeightAction, + checkContainersForAutoHeight: checkContainersForAutoHeightAction, }; export default connect(null, mapDispatchToProps)(EditorContextProvider); diff --git a/app/client/src/pages/AppViewer/index.tsx b/app/client/src/pages/AppViewer/index.tsx index a709818f39..a770a6b90f 100644 --- a/app/client/src/pages/AppViewer/index.tsx +++ b/app/client/src/pages/AppViewer/index.tsx @@ -45,6 +45,11 @@ import { initAppViewer } from "actions/initActions"; import { WidgetGlobaStyles } from "globalStyles/WidgetGlobalStyles"; import { getAppsmithConfigs } from "@appsmith/configs"; +import { + checkContainersForAutoHeightAction, + updateWidgetAutoHeightAction, +} from "actions/autoHeightActions"; + const AppViewerBody = styled.section<{ hasPages: boolean; headerHeight: number; @@ -227,6 +232,13 @@ function AppViewer(props: Props) { [triggerEvalOnMetaUpdate, dispatch], ); + const updateWidgetAutoHeightCallback = useCallback( + (widgetId: string, height: number) => { + dispatch(updateWidgetAutoHeightAction(widgetId, height)); + }, + [updateWidgetAutoHeightAction, dispatch], + ); + return ( { + it("should return the initial state", () => { + expect(reducer(undefined, { type: "", payload: "" })).toEqual({}); + }); + + it("should set the new auto height layout tree", () => { + const type = ReduxActionTypes.SET_AUTO_HEIGHT_LAYOUT_TREE; + const payload = { + tree: { + 0: { + aboves: [], + belows: [], + topRow: 0, + bottomRow: 0, + originalTopRow: 0, + originalBottomRow: 0, + }, + }, + }; + + const expected = { + 0: { + aboves: [], + belows: [], + topRow: 0, + bottomRow: 0, + originalTopRow: 0, + originalBottomRow: 0, + }, + }; + + expect(reducer(undefined, { type, payload })).toEqual(expected); + }); + + it("should augment the auto height layout tree further in the state", () => { + const type = ReduxActionTypes.SET_AUTO_HEIGHT_LAYOUT_TREE; + const payload = { + tree: { + 0: { + aboves: [], + belows: [], + topRow: 0, + bottomRow: 0, + originalTopRow: 0, + originalBottomRow: 0, + }, + }, + }; + + const state = reducer(undefined, { type, payload }); + + const payload2 = { + tree: { + 0: { + aboves: [], + belows: [1], + topRow: 0, + bottomRow: 0, + originalTopRow: 0, + originalBottomRow: 0, + }, + 1: { + aboves: [0], + belows: [], + topRow: 10, + bottomRow: 10, + originalTopRow: 10, + originalBottomRow: 10, + }, + }, + }; + + const expected = { + 0: { + aboves: [], + belows: [1], + topRow: 0, + bottomRow: 0, + originalTopRow: 0, + originalBottomRow: 0, + }, + 1: { + aboves: [0], + belows: [], + topRow: 10, + bottomRow: 10, + originalTopRow: 10, + originalBottomRow: 10, + }, + }; + + const state2 = reducer(state, { type, payload: payload2 }); + + expect(state2).toEqual(expected); + }); +}); diff --git a/app/client/src/reducers/entityReducers/autoHeightReducers/autoHeightLayoutTreeReducer.ts b/app/client/src/reducers/entityReducers/autoHeightReducers/autoHeightLayoutTreeReducer.ts new file mode 100644 index 0000000000..12ad50bbd1 --- /dev/null +++ b/app/client/src/reducers/entityReducers/autoHeightReducers/autoHeightLayoutTreeReducer.ts @@ -0,0 +1,56 @@ +import { createImmerReducer } from "utils/ReducerUtils"; +import { + ReduxAction, + ReduxActionTypes, +} from "@appsmith/constants/ReduxActionConstants"; +import { TreeNode } from "utils/autoHeight/constants"; +import { xor } from "lodash"; + +export type AutoHeightLayoutTreePayload = { + tree: Record; + canvasLevelMap: Record; +}; + +export type AutoHeightLayoutTreeReduxState = { + [widgetId: string]: TreeNode & { level?: number }; +}; +const initialState: AutoHeightLayoutTreeReduxState = {}; + +const autoHeightLayoutTreeReducer = createImmerReducer(initialState, { + [ReduxActionTypes.SET_AUTO_HEIGHT_LAYOUT_TREE]: ( + state: AutoHeightLayoutTreeReduxState, + action: ReduxAction, + ) => { + const { tree } = action.payload; + const diff = xor(Object.keys(state), ...Object.keys(tree)); + for (const widgetId in diff) { + delete state[widgetId]; + } + for (const widgetId in tree) { + if (state[widgetId]) { + const differentAboves = xor( + state[widgetId].aboves, + tree[widgetId].aboves, + ); + if (differentAboves.length > 0) { + state[widgetId].aboves = tree[widgetId].aboves; + } + + const differentBelows = xor( + state[widgetId].belows, + tree[widgetId].belows, + ); + if (differentBelows.length > 0) { + state[widgetId].belows = tree[widgetId].belows; + } + + state[widgetId].topRow = tree[widgetId].topRow; + state[widgetId].bottomRow = tree[widgetId].bottomRow; + } else { + state[widgetId] = tree[widgetId]; + } + } + }, +}); + +export default autoHeightLayoutTreeReducer; diff --git a/app/client/src/reducers/entityReducers/autoHeightReducers/canvasLevelsReducer.test.ts b/app/client/src/reducers/entityReducers/autoHeightReducers/canvasLevelsReducer.test.ts new file mode 100644 index 0000000000..8fa02fed19 --- /dev/null +++ b/app/client/src/reducers/entityReducers/autoHeightReducers/canvasLevelsReducer.test.ts @@ -0,0 +1,44 @@ +import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; +import reducer from "./canvasLevelsReducer"; + +describe("Canvas Levels Reducer", () => { + it("should return the initial state", () => { + expect(reducer(undefined, { type: "", payload: "" })).toEqual({}); + }); + + it("should set the new canvas mappings to the state", () => { + const type = ReduxActionTypes.SET_CANVAS_LEVELS_MAP; + const payload = { + canvasLevelMap: { + 0: 0, + }, + }; + const expected = { + 0: 0, + }; + + expect(reducer(undefined, { type, payload })).toEqual(expected); + }); + + it("should augment the further canvas mappings to the state", () => { + const type = ReduxActionTypes.SET_CANVAS_LEVELS_MAP; + const payload = { + canvasLevelMap: { + 0: 0, + }, + }; + + const state = reducer(undefined, { type, payload }); + + const payload2 = { + canvasLevelMap: { + 1: 1, + }, + }; + const expected = { + 0: 0, + 1: 1, + }; + expect(reducer(state, { type, payload: payload2 })).toEqual(expected); + }); +}); diff --git a/app/client/src/reducers/entityReducers/autoHeightReducers/canvasLevelsReducer.ts b/app/client/src/reducers/entityReducers/autoHeightReducers/canvasLevelsReducer.ts new file mode 100644 index 0000000000..529a11760e --- /dev/null +++ b/app/client/src/reducers/entityReducers/autoHeightReducers/canvasLevelsReducer.ts @@ -0,0 +1,29 @@ +import { createImmerReducer } from "utils/ReducerUtils"; +import { + ReduxAction, + ReduxActionTypes, +} from "@appsmith/constants/ReduxActionConstants"; +import { AutoHeightLayoutTreePayload } from "./autoHeightLayoutTreeReducer"; + +export type CanvasLevelsPayload = Record; + +export type CanvasLevelsReduxState = { + [widgetId: string]: number; +}; + +const initialState: CanvasLevelsReduxState = {}; + +const canvasLevelsReducer = createImmerReducer(initialState, { + [ReduxActionTypes.SET_CANVAS_LEVELS_MAP]: ( + state: CanvasLevelsReduxState, + action: ReduxAction, + ) => { + const { canvasLevelMap } = action.payload; + for (const widgetId in canvasLevelMap) { + if (state[widgetId] !== canvasLevelMap[widgetId]) + state[widgetId] = canvasLevelMap[widgetId]; + } + }, +}); + +export default canvasLevelsReducer; diff --git a/app/client/src/reducers/entityReducers/canvasWidgetsReducer.test.ts b/app/client/src/reducers/entityReducers/canvasWidgetsReducer.test.ts new file mode 100644 index 0000000000..9c755840f9 --- /dev/null +++ b/app/client/src/reducers/entityReducers/canvasWidgetsReducer.test.ts @@ -0,0 +1,135 @@ +import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; +import reducer from "./canvasWidgetsReducer"; + +describe("Canvas Widgets Reducer", () => { + it("should return the initial state", () => { + expect(reducer(undefined, { type: "", payload: "" })).toEqual({}); + }); + + it("should update the paths", () => { + const initialState = { + "0": { children: ["xyz123"] }, + xyz123: { + bottomRow: 20, + topRow: 10, + someValue: { + apple: "orange", + }, + }, + }; + const type = ReduxActionTypes.UPDATE_MULTIPLE_WIDGET_PROPERTIES; + const payload = { + xyz123: [ + { + propertyPath: "someValue.apple", + propertyValue: "apple", + }, + ], + }; + const expected = { + "0": { children: ["xyz123"] }, + xyz123: { + bottomRow: 20, + topRow: 10, + someValue: { + apple: "apple", + }, + }, + }; + + expect(reducer(initialState, { type, payload })).toEqual(expected); + }); + + it("should create paths if they donot exist", () => { + const initialState = { + "0": { children: ["xyz123"] }, + xyz123: { + bottomRow: 20, + topRow: 10, + someValue: { + apple: "orange", + }, + }, + }; + const type = ReduxActionTypes.UPDATE_MULTIPLE_WIDGET_PROPERTIES; + const payload = { + xyz123: [ + { + propertyPath: "someValue.games.ball", + propertyValue: ["football"], + }, + ], + }; + const expected = { + "0": { children: ["xyz123"] }, + xyz123: { + bottomRow: 20, + topRow: 10, + someValue: { + apple: "orange", + games: { + ball: ["football"], + }, + }, + }, + }; + + expect(reducer(initialState, { type, payload })).toEqual(expected); + }); + + it("should not update the paths if the values are the same", () => { + const initialState = { + "0": { children: ["xyz123"] }, + xyz123: { + bottomRow: 20, + topRow: 10, + someValue: { + apple: "orange", + }, + }, + }; + const type = ReduxActionTypes.UPDATE_MULTIPLE_WIDGET_PROPERTIES; + const payload = { + xyz123: [ + { + propertyPath: "someValue.apple", + propertyValue: "orange", + }, + ], + }; + + // Reference equality check using toBe + expect(reducer(initialState, { type, payload })).toBe(initialState); + }); + + it("should have the same reference for paths not updated", () => { + const initialState = { + "0": { children: ["xyz123"] }, + xyz123: { + bottomRow: 20, + topRow: 10, + someValue: { + apple: "orange", + games: { + ball: ["football"], + }, + }, + }, + }; + const type = ReduxActionTypes.UPDATE_MULTIPLE_WIDGET_PROPERTIES; + const payload = { + xyz123: [ + { + propertyPath: "someValue.apple", + propertyValue: "orange", + }, + ], + }; + + const result = reducer(initialState, { type, payload }).xyz123.someValue + .games; + + // Reference equality check using toBe + expect(result).toBe(initialState.xyz123.someValue.games); + }); +}); diff --git a/app/client/src/reducers/entityReducers/canvasWidgetsReducer.tsx b/app/client/src/reducers/entityReducers/canvasWidgetsReducer.tsx index c079063970..ec5313c26e 100644 --- a/app/client/src/reducers/entityReducers/canvasWidgetsReducer.tsx +++ b/app/client/src/reducers/entityReducers/canvasWidgetsReducer.tsx @@ -6,10 +6,23 @@ import { } from "@appsmith/constants/ReduxActionConstants"; import { WidgetProps } from "widgets/BaseWidget"; import { Diff, diff } from "deep-diff"; -import { uniq } from "lodash"; +import { uniq, get, set } from "lodash"; const initialState: CanvasWidgetsReduxState = {}; +/* This type is an object whose keys are widgetIds and values are arrays with property paths +and property values +For example: +{ "xyz123": [{ propertyPath: "bottomRow", propertyValue: 20 }] } +*/ +export type UpdateWidgetsPayload = Record< + string, + Array<{ + propertyPath: string; + propertyValue: unknown; + }> +>; + export type FlattenedWidgetProps = | (WidgetProps & { children?: string[]; @@ -69,6 +82,26 @@ const canvasWidgetsReducer = createImmerReducer(initialState, { } } }, + [ReduxActionTypes.UPDATE_MULTIPLE_WIDGET_PROPERTIES]: ( + state: CanvasWidgetsReduxState, + action: ReduxAction, + ) => { + // For each widget whose properties we would like to update + for (const [widgetId, propertyPathsToUpdate] of Object.entries( + action.payload, + )) { + // Iterate through each property to update in `widgetId` + propertyPathsToUpdate.forEach(({ propertyPath, propertyValue }) => { + const path = `${widgetId}.${propertyPath}`; + // Get original value in reducer + const originalPropertyValue = get(state, path); + // If the original and new values are different + if (propertyValue !== originalPropertyValue) + // Set the new values + set(state, path, propertyValue); + }); + } + }, }); export interface CanvasWidgetsReduxState { [widgetId: string]: FlattenedWidgetProps; diff --git a/app/client/src/reducers/entityReducers/index.ts b/app/client/src/reducers/entityReducers/index.ts index 86d7de4f1b..42cafb01c4 100644 --- a/app/client/src/reducers/entityReducers/index.ts +++ b/app/client/src/reducers/entityReducers/index.ts @@ -10,6 +10,8 @@ import metaReducer from "./metaReducer"; import pageListReducer from "./pageListReducer"; import pluginsReducer from "reducers/entityReducers/pluginsReducer"; import widgetConfigReducer from "./widgetConfigReducer"; +import autoHeightLayoutTreeReducer from "./autoHeightReducers/autoHeightLayoutTreeReducer"; +import canvasLevelsReducer from "./autoHeightReducers/canvasLevelsReducer"; const entityReducer = combineReducers({ canvasWidgets: canvasWidgetsReducer, @@ -23,6 +25,8 @@ const entityReducer = combineReducers({ meta: metaReducer, app: appReducer, jsActions: jsActionsReducer, + autoHeightLayoutTree: autoHeightLayoutTreeReducer, + canvasLevels: canvasLevelsReducer, }); export default entityReducer; diff --git a/app/client/src/utils/autoHeight/constants.ts b/app/client/src/utils/autoHeight/constants.ts new file mode 100644 index 0000000000..8712c3dcf6 --- /dev/null +++ b/app/client/src/utils/autoHeight/constants.ts @@ -0,0 +1,8 @@ +export type TreeNode = { + aboves: string[]; + belows: string[]; + topRow: number; + bottomRow: number; + originalTopRow: number; + originalBottomRow: number; +};