Skip to content

Upgrade node packages + Optimisations to improve memory consumption #1697

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
80a2d08
upgrade react-resize-detector, replace ReactResizeDetector comp with …
raheeliftikhar5 Apr 29, 2025
e2a39ef
upgrade react-draggable, added missing nodeRef
raheeliftikhar5 Apr 29, 2025
2130263
replaced react-quill with react-quill-new
raheeliftikhar5 Apr 29, 2025
9ae9a9c
removed react-sortabled-hoc, used dnd-kit for sorting
raheeliftikhar5 Apr 29, 2025
8266951
fix icon comp, icon button when no icon is selected
raheeliftikhar5 Apr 29, 2025
61d5a45
added memoization on table comp
raheeliftikhar5 Apr 29, 2025
41f6276
upgrade comps
raheeliftikhar5 Apr 29, 2025
73c613b
build lowcoder-core after upgrading react version
raheeliftikhar5 Apr 29, 2025
e7c960b
upgraded react, react-dom in lowcoderc-comps + replaced ReactResizeDe…
raheeliftikhar5 Apr 29, 2025
2e1fd49
upgrade packages
raheeliftikhar5 Apr 29, 2025
eae5b3d
optimise drawer comp
raheeliftikhar5 May 21, 2025
9cac3cf
optimise lowcoder-design components
raheeliftikhar5 May 21, 2025
c2c88ec
optimise shared components
raheeliftikhar5 May 21, 2025
707e3e0
optimise table comp, toolbar, filters, summary rows and different col…
raheeliftikhar5 May 21, 2025
405822b
optimise button component
raheeliftikhar5 May 21, 2025
da075f5
optimise editor view
raheeliftikhar5 May 21, 2025
0543b12
optimise canvas view/inner grid, root comp, gridLayout, gridItem and …
raheeliftikhar5 May 21, 2025
05ee98b
optimise form components
raheeliftikhar5 May 21, 2025
c2680f3
optimise modal comp
raheeliftikhar5 May 21, 2025
371a9bc
optimise event handler control
raheeliftikhar5 May 21, 2025
6ef3c5e
remove antd's react 19 patch
raheeliftikhar5 May 21, 2025
6ab43b4
fixed query variable value when used with event handler control
raheeliftikhar5 May 21, 2025
0bdc38c
Merge branch 'dev' into feature/support-react-19
FalkWolsky May 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
optimise lowcoder-design components
  • Loading branch information
raheeliftikhar5 committed May 22, 2025
commit 9cac3cf7183bd3094e89bebe2410fbdb6440a977
10 changes: 7 additions & 3 deletions client/packages/lowcoder-design/src/components/Modal/handler.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import styled, { css } from "styled-components";
import { memo, useMemo } from "react";

type ResizeHandleAxis = "s" | "w" | "e" | "n" | "sw" | "nw" | "se" | "ne";
type ReactRef<T extends HTMLElement> = {
Expand Down Expand Up @@ -83,8 +84,11 @@ const ResizeHandle = styled.div<{ $axis: string }>`
${(props) => (["sw", "nw", "se", "ne"].indexOf(props.$axis) >= 0 ? CornerHandle : "")};
`;

const Handle = (axis: ResizeHandleAxis, ref: ReactRef<HTMLDivElement>) => {
return <ResizeHandle ref={ref} $axis={axis} className={`react-resizable-handle`}></ResizeHandle>;
};
// Memoize Handle component
const Handle = memo((axis: ResizeHandleAxis, ref: ReactRef<HTMLDivElement>) => {
return <ResizeHandle ref={ref} $axis={axis} className="react-resizable-handle" />;
});

Handle.displayName = 'Handle';

export default Handle;
65 changes: 40 additions & 25 deletions client/packages/lowcoder-design/src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { default as AntdModal, ModalProps as AntdModalProps } from "antd/es/modal";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { Resizable, ResizeHandle } from "react-resizable";
import { useResizeDetector } from "react-resize-detector";
import Handle from "./handler";
Expand Down Expand Up @@ -39,45 +39,60 @@ export function Modal(props: ModalProps) {

const [width, setWidth] = useState<number>();
const [height, setHeight] = useState<number>();

// Memoize style object
const modalStyles = useMemo(() => ({
body: {
height: height ?? modalHeight,
...styles?.body,
}
}), [height, modalHeight, styles?.body]);

// Memoize event handlers
const handleResizeStart = useCallback((event: React.SyntheticEvent, { node, size, handle }: { node: HTMLElement; size: { width: number; height: number }; handle: ResizeHandle }) => {
props.onResizeStart?.(event, node, size, handle);
}, [props.onResizeStart]);

const handleResize = useCallback((event: React.SyntheticEvent, { node, size, handle }: { node: HTMLElement; size: { width: number; height: number }; handle: ResizeHandle }) => {
setWidth(size.width);
setHeight(size.height);
props.onResize?.(event, node, size, handle);
}, [props.onResize]);

const handleResizeStop = useCallback((event: React.SyntheticEvent, { node, size, handle }: { node: HTMLElement; size: { width: number; height: number }; handle: ResizeHandle }) => {
props.onResizeStop?.(event, node, size, handle);
}, [props.onResizeStop]);

useEffect(() => {
setWidth(undefined);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [modalWidth]);

useEffect(() => {
setHeight(undefined);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [modalHeight]);

const { width: detectWidth, height: detectHeight, ref } = useResizeDetector();
// log.info("Modal. modalWidth: ", modalWidth, " width: ", size?.w, " detectWidth: ", detectWidth);

// Memoize Resizable props
const resizableProps = useMemo(() => ({
width: width ?? detectWidth ?? 0,
height: height ?? detectHeight ?? 0,
resizeHandles,
handle: Handle,
onResizeStart: handleResizeStart,
onResize: handleResize,
onResizeStop: handleResizeStop
}), [width, detectWidth, height, detectHeight, resizeHandles, handleResizeStart, handleResize, handleResizeStop]);

return (
<AntdModal
width={width ?? modalWidth}
styles={{
body: {
height: height ?? modalHeight,
...styles?.body,
}
}}
styles={modalStyles}
{...otherProps}
>
<Resizable
width={width ?? detectWidth ?? 0}
height={height ?? detectHeight ?? 0}
resizeHandles={resizeHandles}
handle={Handle}
onResizeStart={(event, { node, size, handle }) =>
props.onResizeStart?.(event, node, size, handle)
}
onResize={(event, { node, size, handle }) => {
setWidth(size.width);
setHeight(size.height);
props.onResize?.(event, node, size, handle);
}}
onResizeStop={(event, { node, size, handle }) =>
props.onResizeStop?.(event, node, size, handle)
}
>
<Resizable {...resizableProps}>
<div ref={ref} style={{ height: "100%" }}>
{children}
</div>
Expand Down
57 changes: 36 additions & 21 deletions client/packages/lowcoder-design/src/components/ScrollBar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useCallback, useMemo } from "react";
import SimpleBar from "simplebar-react";
import styled from "styled-components";
import { DebouncedFunc } from 'lodash'; // Assuming you're using lodash's DebouncedFunc type
Expand Down Expand Up @@ -57,7 +57,7 @@ interface IProps {
children: React.ReactNode;
className?: string;
height?: string;
overflow?:string,
overflow?: string,
style?: React.CSSProperties; // Add this line to include a style prop
scrollableNodeProps?: {
onScroll: DebouncedFunc<(e: any) => void>;
Expand All @@ -68,7 +68,7 @@ interface IProps {
suffixNode?: React.ReactNode;
}

export const ScrollBar = ({
export const ScrollBar = React.memo(({
className,
children,
style,
Expand All @@ -80,31 +80,46 @@ export const ScrollBar = ({
suffixNode,
...otherProps
}: IProps) => {
const height = style?.height ?? '100%';
// You can now use the style prop directly or pass it to SimpleBar
const combinedStyle = { ...style, height }; // Example of combining height with passed style
// Memoize the combined style to prevent unnecessary re-renders
const combinedStyle = useMemo(() => {
const height = style?.height ?? '100%';
return { ...style, height };
}, [style]);

// Memoize the render function to prevent recreation on every render
const renderContent = useCallback(({ scrollableNodeProps, contentNodeProps }: any) => (
<div {...scrollableNodeProps}>
{prefixNode}
<div {...contentNodeProps}>
{children}
</div>
{suffixNode}
</div>
), [prefixNode, children, suffixNode]);

return hideScrollbar ? (
<ScrollBarWrapper className={className}>
<ScrollBarWrapper
className={className}
$hideplaceholder={$hideplaceholder}
$overflow={overflow}
>
{prefixNode}
{children}
{suffixNode}
</ScrollBarWrapper>
) : (
<ScrollBarWrapper className={className}>
<SimpleBar style={combinedStyle} scrollableNodeProps={scrollableNodeProps} {...otherProps}>
{({ scrollableNodeProps, contentNodeProps }) => {
return (
<div {...scrollableNodeProps as any}>
{prefixNode}
<div {...contentNodeProps as any}>
{children}
</div>
{suffixNode}
</div>
);
}}
<ScrollBarWrapper
className={className}
$hideplaceholder={$hideplaceholder}
$overflow={overflow}
>
<SimpleBar
style={combinedStyle}
scrollableNodeProps={scrollableNodeProps}
{...otherProps}
>
{renderContent}
</SimpleBar>
</ScrollBarWrapper>
);
};
});
58 changes: 36 additions & 22 deletions client/packages/lowcoder-design/src/components/Section.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { trans } from "i18n/design";
import React, { ReactNode, useContext } from "react";
import React, { ReactNode, useContext, useCallback, useMemo } from "react";
import styled from "styled-components";
import { ReactComponent as Packup } from "icons/v1/icon-Pack-up.svg";
import { labelCss } from "./Label";
Expand All @@ -14,6 +14,7 @@ const SectionItem = styled.div<{ $width?: number }>`
border-bottom: none;
}
`;

const SectionLabel = styled.div`
${labelCss};
flex-grow: 1;
Expand Down Expand Up @@ -64,6 +65,10 @@ const SectionLabelDiv = styled.div`
}
`;

const ButtonContainer = styled.div`
display: flex;
`;

const ShowChildren = styled.div<{ $show?: string; $noMargin?: boolean }>`
display: ${(props) => props.$show || "none"};
flex-direction: column;
Expand All @@ -80,6 +85,7 @@ const TooltipWrapper = styled.span`
white-space: pre-wrap;
color:#fff;
`;

interface ISectionConfig<T> {
name?: string;
open?: boolean;
Expand Down Expand Up @@ -109,59 +115,67 @@ export const PropertySectionContext = React.createContext<PropertySectionContext
state: {},
});

export const BaseSection = (props: ISectionConfig<ReactNode>) => {
const { name,hasTooltip } = props;
const TOOLTIP_CONTENT = (
<TooltipWrapper>
Here you can enter the animation type codes. Like bounce, swing or
tada. Read more about all possible codes at:{" "}
<a href="https://animate.style">https://animate.style</a>
</TooltipWrapper>
);

export const BaseSection = React.memo((props: ISectionConfig<ReactNode>) => {
const { name, hasTooltip } = props;
const { compName, state, toggle } = useContext(PropertySectionContext);
const open = props.open !== undefined ? props.open : name ? state[compName]?.[name] !== false : true;

// console.log("open", open, props.open);

const handleToggle = () => {
const handleToggle = useCallback(() => {
if (!name) {
return;
}
toggle(compName, name);
};
}, [name, compName, toggle]);

const tooltipContent = useMemo(() => hasTooltip ? TOOLTIP_CONTENT : null, [hasTooltip]);

const getPopupContainer = useCallback((node: HTMLElement) => {
return (node.closest('.react-grid-item') as HTMLElement) || document.body;
}, []);

return (
<SectionItem $width={props.width} style={props.style}>
{props.name && (
<SectionLabelDiv onClick={handleToggle} className={'section-header'}>
<SectionLabel>{props.name}</SectionLabel>
<div style={{display: 'flex'}}>
<ButtonContainer>
{open && props.additionalButton}
<PackupIcon deg={open ? 'rotate(0deg)' : 'rotate(180deg)'} />
</div>
</ButtonContainer>
</SectionLabelDiv>
)}
<Tooltip
title={
hasTooltip && (
<TooltipWrapper>
Here you can enter the animation type codes. Like bounce, swing or
tada. Read more about all possible codes at:{" "}
<a href="https://animate.style">https://animate.style</a>
</TooltipWrapper>
)
}
title={tooltipContent}
arrow={{
pointAtCenter: true,
}}
placement="top"
color="#2c2c2c"
getPopupContainer={(node: any) => node.closest('.react-grid-item')}
getPopupContainer={getPopupContainer}
>
<ShowChildren $show={open ? 'flex' : 'none'} $noMargin={props.noMargin}>
{props.children}
</ShowChildren>
</Tooltip>
</SectionItem>
);
};
});

export function Section(props: ISectionConfig<ControlNode>) {
BaseSection.displayName = 'BaseSection';

export const Section = React.memo((props: ISectionConfig<ControlNode>) => {
return controlItem({ filterText: props.name, searchChild: true }, <BaseSection {...props} />);
}
});

Section.displayName = 'Section';

// common section names
export const sectionNames = {
Expand Down
42 changes: 29 additions & 13 deletions client/packages/lowcoder-design/src/components/Tab.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styled, { css } from "styled-components";
import React from "react";
import React, { useCallback, useMemo } from "react";

const HeaderDiv = styled.div`
width: 312px;
Expand Down Expand Up @@ -79,26 +79,42 @@ interface ITabs {
activeKey: string;
}

const Tabs = (props: ITabs) => {
const Tabs = React.memo((props: ITabs) => {
const { onChange, tabsConfig, activeKey } = props;
const activeTab = tabsConfig.find((c) => c.key === activeKey) || tabsConfig[0];

const activeTab = useMemo(() =>
tabsConfig.find((c) => c.key === activeKey) || tabsConfig[0],
[tabsConfig, activeKey]
);

const handleTabClick = useCallback((key: string) => {
onChange(key);
}, [onChange]);

const renderTab = useCallback((tab: ITabsConfig) => {
const isActive = activeTab.key === tab.key;
return (
<IconAndName
key={tab.key}
onClick={() => handleTabClick(tab.key)}
$isActive={isActive}
>
{tab.icon}
<Text $color={isActive ? "#222222" : "#8b8fa3"}>{tab.title}</Text>
</IconAndName>
);
}, [activeTab.key, handleTabClick]);

return (
<>
<HeaderDiv>
{props.tabsConfig.map((tab) => {
const isActive = activeTab.key === tab.key;
return (
<IconAndName key={tab.key} onClick={() => onChange(tab.key)} $isActive={isActive}>
{tab.icon}
<Text $color={isActive ? "#222222" : "#8b8fa3"}>{tab.title}</Text>
</IconAndName>
);
})}
{tabsConfig.map(renderTab)}
</HeaderDiv>
<ChildDiv>{activeTab.content}</ChildDiv>
</>
);
};
});

Tabs.displayName = 'Tabs';

export { Tabs };
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy