Skip to content

Adding support for horizontal orientation for List Component #787

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 2 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ export function InnerGrid(props: ViewPropsWithSelect) {
const editorState = useContext(EditorContext);
const { readOnly } = useContext(ExternalEditorContext);

// Falk: TODO: Here we can define the inner grid columns dynamically
//Added By Aqib Mirza
const defaultGrid =
useContext(ThemeContext)?.theme?.gridColumns ||
Expand Down
79 changes: 50 additions & 29 deletions client/packages/lowcoder/src/comps/comps/listViewComp/listView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BackgroundColorContext } from "comps/utils/backgroundColorContext";
import _ from "lodash";
import { ConstructorToView, deferAction } from "lowcoder-core";
import { HintPlaceHolder, ScrollBar, pageItemRender } from "lowcoder-design";
import { RefObject, useContext, useEffect, useMemo, useRef } from "react";
import { RefObject, useContext, createContext, useMemo, useRef } from "react";
import ReactResizeDetector from "react-resize-detector";
import styled from "styled-components";
import { checkIsMobile } from "util/commonUtils";
Expand Down Expand Up @@ -40,21 +40,34 @@ const BodyWrapper = styled.div<{ $autoHeight: boolean }>`
height: ${(props) => (props.$autoHeight ? "100%" : "calc(100% - 32px)")};
`;

const FlexWrapper = styled.div`
const FlexWrapper = styled.div`
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: 'wrap'};
`;

const ContainerInListView = (props: ContainerBaseProps) => {
const ListOrientationWrapper = styled.div<{ $isHorizontal: boolean, $autoHeight : boolean }>`
height: ${(props) => (props.$autoHeight ? "auto" : "100%")};
display: flex;
flex-direction: ${(props) => (props.$isHorizontal ? "row" : "column")};
height: 100%;
`;

const MinHorizontalWidthContext = createContext(0);

const ContainerInListView = (props: ContainerBaseProps ) => {
const minHorizontalWidth = useContext(MinHorizontalWidthContext);
return (
<InnerGrid
{...props}
emptyRows={15}
containerPadding={[4, 4]}
hintPlaceholder={HintPlaceHolder}
/>
<div style={{ width: minHorizontalWidth > 0 ? `${minHorizontalWidth}px` : "100%"}}>
<InnerGrid
{...props}
emptyRows={15}
containerPadding={[4, 4]}
hintPlaceholder={HintPlaceHolder}
/>
</div>
);
};

Expand All @@ -66,9 +79,10 @@ type ListItemProps = {
scrollContainerRef?: RefObject<HTMLDivElement>;
minHeight?: string;
unMountFn?: () => void;
minHorizontalWidth: number;
};

function ListItem(props: ListItemProps) {
function ListItem({ minHorizontalWidth, ...props }: ListItemProps) {
const { itemIdx, offset, containerProps, autoHeight, scrollContainerRef, minHeight } = props;

// disable the unmount function to save user's state with pagination
Expand All @@ -80,23 +94,25 @@ function ListItem(props: ListItemProps) {
// }, []);

return (
<ContainerInListView
layout={containerProps.layout}
items={gridItemCompToGridItems(containerProps.items)}
positionParams={containerProps.positionParams}
// all layout changes should only reflect on the commonContainer
dispatch={itemIdx === offset ? containerProps.dispatch : _.noop}
style={{ height: "100%", backgroundColor: "transparent", flex: "auto" }}
autoHeight={autoHeight}
isDroppable={itemIdx === offset}
isDraggable={itemIdx === offset}
isResizable={itemIdx === offset}
isSelectable={itemIdx === offset}
scrollContainerRef={scrollContainerRef}
overflow={"hidden"}
minHeight={minHeight}
enableGridLines={true}
/>
<MinHorizontalWidthContext.Provider value={minHorizontalWidth}>
<ContainerInListView
layout={containerProps.layout}
items={gridItemCompToGridItems(containerProps.items)}
positionParams={containerProps.positionParams}
// all layout changes should only reflect on the commonContainer
dispatch={itemIdx === offset ? containerProps.dispatch : _.noop}
style={{ height: "100%", backgroundColor: "transparent", flex: "auto"}}
autoHeight={autoHeight}
isDroppable={itemIdx === offset}
isDraggable={itemIdx === offset}
isResizable={itemIdx === offset}
isSelectable={itemIdx === offset}
scrollContainerRef={scrollContainerRef}
overflow={"hidden"}
minHeight={minHeight}
enableGridLines={true}
/>
</MinHorizontalWidthContext.Provider>
);
}

Expand Down Expand Up @@ -126,6 +142,8 @@ export function ListView(props: Props) {
);
const autoHeight = useMemo(() => children.autoHeight.getView(), [children.autoHeight]);
const scrollbars = useMemo(() => children.scrollbars.getView(), [children.scrollbars]);
const horizontal = useMemo(() => children.horizontal.getView(), [children.horizontal]);
const minHorizontalWidth = useMemo(() => children.minHorizontalWidth.getView(), [children.minHorizontalWidth]);
const noOfColumns = useMemo(
() => Math.max(1, children.noOfColumns.getView()),
[children.noOfColumns]
Expand Down Expand Up @@ -163,7 +181,8 @@ export function ListView(props: Props) {
key={rowIdx}
style={{
height: rowHeight,
// border: "0.5px solid #d9d9d9"
width: 100 / noOfColumns + "%",
minWidth: minHorizontalWidth,
}}
>
<FlexWrapper>
Expand Down Expand Up @@ -198,6 +217,7 @@ export function ListView(props: Props) {
scrollContainerRef={ref}
minHeight={minHeight}
unMountFn={unMountFn}
minHorizontalWidth={horizontal ? minHorizontalWidth : 0}
/>
);
})}
Expand All @@ -214,10 +234,11 @@ export function ListView(props: Props) {
return (
<BackgroundColorContext.Provider value={style.background}>
<ListViewWrapper $style={style} $paddingWidth={paddingWidth}>

<BodyWrapper ref={ref} $autoHeight={autoHeight}>
<ScrollBar style={{ height: autoHeight ? "auto" : "100%", margin: "0px", padding: "0px" }} hideScrollbar={!scrollbars}>
<>{<ReactResizeDetector onResize={(width?: number, height?: number) => { if (height) setListHeight(height); }} observerOptions={{ box: "border-box" }} >
<div style={{ height: autoHeight ? "auto" : "100%" }}>{renders}</div>
<ListOrientationWrapper $isHorizontal={horizontal} $autoHeight={autoHeight}>{renders}</ListOrientationWrapper>
</ReactResizeDetector>}</>
</ScrollBar>
</BodyWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const childrenMap = {
showBorder: BoolControl,
pagination: withDefault(PaginationControl, { pageSize: "6" }),
style: styleControl(ListViewStyle),
horizontal: withDefault(BoolControl, false),
minHorizontalWidth: withDefault(NumberControl, 100),
};

const ListViewTmpComp = new UICompBuilder(childrenMap, () => <></>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,19 @@ export function listPropertyView(compType: ListCompType) {
{(useContext(EditorContext).editorModeStatus === "layout" || useContext(EditorContext).editorModeStatus === "both") && (
<><Section name={sectionNames.layout}>
{children.autoHeight.getPropertyView()}
{!children.autoHeight.getView() &&
{(!children.autoHeight.getView() || children.horizontal.getView()) &&
children.scrollbars.propertyView({
label: trans("prop.scrollbar"),
}
)}
{children.horizontal.propertyView({
label: trans("prop.horizontal"),
})}
{children.horizontal.getView() && (
children.minHorizontalWidth.propertyView({
label: trans("prop.minHorizontalWidth"),
})
)}
</Section>
<Section name={sectionNames.style}>
{children.style.getPropertyView()}
Expand Down
2 changes: 2 additions & 0 deletions client/packages/lowcoder/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ export const en = {
"showApp": "Show an App in the content area",
"showAppTooltip": "You can display whole Lowcoder Apps in the content area. Please mind, that for Modules we do not support Inputs, Outputs Events and Methods.",
"baseURL": "Lowcoder API Base URL",
"horizontal": "Horizontal",
"minHorizontalWidth": "Minimum Horizontal Width",
},
"autoHeightProp": {
"auto": "Auto",
Expand Down
2 changes: 2 additions & 0 deletions client/packages/lowcoder/src/i18n/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ prop: {
"showApp": "在内容区域显示应用程序",
"showAppTooltip": "您可以在内容区域显示整个 Lowcoder 应用程序。请注意,对于模块,我们不支持输入、输出事件和方法。",
"baseURL": "Lowcoder API 基本 URL",
"horizontal": "水平",
"minHorizontalWidth": "最小水平宽度",
},
autoHeightProp: {
auto: "自动",
Expand Down