Skip to content

Commit de1bc70

Browse files
feat: table row fixed/auto height + column ellipsis/wrap switch
1 parent 9d68bb7 commit de1bc70

File tree

8 files changed

+115
-34
lines changed

8 files changed

+115
-34
lines changed

client/packages/lowcoder/src/components/table/EditableCell.tsx

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface CellProps {
3434
size?: string;
3535
candidateTags?: string[];
3636
candidateStatus?: { text: string; status: StatusType }[];
37+
textOverflow?: boolean;
3738
}
3839

3940
export type CellViewReturn = (props: CellProps) => ReactNode;
@@ -43,17 +44,6 @@ export type EditViewFn<T> = (props: {
4344
onChangeEnd: () => void;
4445
}) => ReactNode;
4546

46-
export const SizeWrapper = styled.div<{ $size?: string }>`
47-
${(props) =>
48-
props.$size &&
49-
`padding: ${
50-
props.$size === "small" ? "8.5px 8px" : props.$size === "large" ? "16.5px 16px" : "12.5px 8px"
51-
};
52-
line-height: 21px;
53-
min-height: ${props.$size === "small" ? "39px" : props.$size === "large" ? "55px" : "47px"};
54-
`}
55-
`;
56-
5747
const BorderDiv = styled.div`
5848
position: absolute;
5949
border: 1.5px solid #315efb;
@@ -127,11 +117,15 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
127117
}
128118

129119
return (
130-
<ColumnTypeView>
120+
<ColumnTypeView
121+
textOverflow={props.textOverflow}
122+
>
131123
{status === "toSave" && !isEditing && <EditableChip />}
132-
<SizeWrapper $size={props.size} onDoubleClick={enterEditFn}>
124+
<div
125+
onDoubleClick={enterEditFn}
126+
>
133127
{normalView}
134-
</SizeWrapper>
128+
</div>
135129
</ColumnTypeView>
136130
);
137131
}

client/packages/lowcoder/src/components/table/columnTypeView.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import React, { useEffect, useMemo, useRef, useState } from "react";
22
import styled from "styled-components";
33

4-
const ColumnTypeViewWrapper = styled.div`
5-
div {
6-
overflow: hidden;
7-
white-space: nowrap;
8-
text-overflow: ellipsis;
9-
word-break: keep-all;
10-
}
4+
const ColumnTypeViewWrapper = styled.div<{
5+
textOverflow?: boolean
6+
}>`
7+
${props => !props.textOverflow && `
8+
div {
9+
overflow: hidden;
10+
white-space: nowrap;
11+
text-overflow: ellipsis;
12+
word-break: keep-all;
13+
}
14+
`}
1115
`;
1216

1317
const ColumnTypeHoverView = styled.div<{
@@ -62,7 +66,10 @@ function childIsOverflow(nodes: HTMLCollection): boolean {
6266
return false;
6367
}
6468

65-
export default function ColumnTypeView(props: { children: React.ReactNode }) {
69+
export default function ColumnTypeView(props: {
70+
children: React.ReactNode,
71+
textOverflow?: boolean,
72+
}) {
6673
const wrapperRef = useRef<HTMLDivElement>(null);
6774
const hoverViewRef = useRef<HTMLDivElement>(null);
6875
const [isHover, setIsHover] = useState(false);
@@ -161,6 +168,7 @@ export default function ColumnTypeView(props: { children: React.ReactNode }) {
161168
<>
162169
<ColumnTypeViewWrapper
163170
ref={wrapperRef}
171+
textOverflow={props.textOverflow}
164172
onMouseEnter={() => {
165173
delayMouseEnter();
166174
}}
@@ -171,7 +179,7 @@ export default function ColumnTypeView(props: { children: React.ReactNode }) {
171179
>
172180
{props.children}
173181
</ColumnTypeViewWrapper>
174-
{isHover && hasOverflow && wrapperRef.current && (
182+
{isHover && hasOverflow && wrapperRef.current && !props.textOverflow && (
175183
<ColumnTypeHoverView
176184
ref={hoverViewRef}
177185
visible={adjustedPosition.done}

client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { ColumnTypeComp, ColumnTypeCompMap } from "./columnTypeComp";
2626
import { ColorControl } from "comps/controls/colorControl";
2727
import { JSONValue } from "util/jsonTypes";
2828
import styled from "styled-components";
29+
import { TextOverflowControl } from "comps/controls/textOverflowControl";
2930

3031
export type Render = ReturnType<ConstructorToComp<typeof RenderComp>["getOriginalComp"]>;
3132
export const RenderComp = withSelectedMultiContext(ColumnTypeComp);
@@ -103,7 +104,8 @@ export const columnChildrenMap = {
103104
borderWidth: withDefault(RadiusControl, ""),
104105
radius: withDefault(RadiusControl, ""),
105106
textSize: withDefault(RadiusControl, ""),
106-
cellColor: CellColorComp,
107+
cellColor: CellColorComp,
108+
textOverflow: withDefault(TextOverflowControl, "ellipsis"),
107109
};
108110

109111
const StyledIcon = styled.span`
@@ -228,6 +230,7 @@ export class ColumnComp extends ColumnInitComp {
228230
preInputNode: <StyledIcon as={TextSizeIcon} title="" />,
229231
placeholder: '14px',
230232
})}
233+
{this.children.textOverflow.getPropertyView()}
231234
{this.children.cellColor.getPropertyView()}
232235
</>
233236
);

client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,10 @@ const TableTh = styled.th<{ width?: number }>`
284284

285285
const TableTd = styled.td<{
286286
background: string;
287-
$style: TableColumnStyleType & {height?: string};
287+
$style: TableColumnStyleType & {rowHeight?: string};
288288
$isEditing: boolean;
289+
$tableSize?: string;
290+
$autoHeight?: boolean;
289291
}>`
290292
.ant-table-row-expand-icon,
291293
.ant-table-row-indent {
@@ -296,15 +298,41 @@ const TableTd = styled.td<{
296298
border-color: ${(props) => props.$style.border};
297299
}
298300
background: ${(props) => props.background} !important;
299-
height: ${(props) => props.$style.height};
300301
border-color: ${(props) => props.$style.border} !important;
301302
border-width: ${(props) => props.$style.borderWidth} !important;
302303
border-radius: ${(props) => props.$style.radius};
303304
padding: 0 !important;
304305
305-
> div > div {
306+
> div {
306307
color: ${(props) => props.$style.text};
307308
font-size: ${(props) => props.$style.textSize};
309+
line-height: 21px;
310+
311+
${(props) => props.$tableSize === 'small' && `
312+
padding: 8.5px 8px;
313+
min-height: ${props.$style.rowHeight || '39px'};
314+
${!props.$autoHeight && `
315+
overflow-y: auto;
316+
max-height: ${props.$style.rowHeight || '39px'};
317+
`};
318+
`};
319+
${(props) => props.$tableSize === 'middle' && `
320+
padding: 12.5px 8px;
321+
min-height: ${props.$style.rowHeight || '47px'};
322+
${!props.$autoHeight && `
323+
overflow-y: auto;
324+
max-height: ${props.$style.rowHeight || '47px'};
325+
`};
326+
`};
327+
${(props) => props.$tableSize === 'large' && `
328+
padding: 16.5px 16px;
329+
min-height: ${props.$style.rowHeight || '55px'};
330+
${!props.$autoHeight && `
331+
overflow-y: auto;
332+
max-height: ${props.$style.rowHeight || '55px'};
333+
`};
334+
`};
335+
308336
&,
309337
> .ant-badge > .ant-badge-status-text,
310338
> div > .markdown-body {
@@ -389,6 +417,8 @@ type CustomTableProps<RecordType> = Omit<TableProps<RecordType>, "components" |
389417
rowColorFn: RowColorViewType;
390418
rowHeightFn: RowHeightViewType;
391419
columnsStyle: TableColumnStyleType;
420+
size?: string;
421+
rowAutoHeight?: boolean;
392422
};
393423

394424
function TableCellView(props: {
@@ -401,6 +431,8 @@ function TableCellView(props: {
401431
children: any;
402432
columnsStyle: TableColumnStyleType;
403433
columnStyle: TableColumnStyleType;
434+
tableSize?: string;
435+
autoHeight?: boolean;
404436
}) {
405437
const {
406438
record,
@@ -412,8 +444,11 @@ function TableCellView(props: {
412444
children,
413445
columnsStyle,
414446
columnStyle,
447+
tableSize,
448+
autoHeight,
415449
...restProps
416450
} = props;
451+
417452
const [editing, setEditing] = useState(false);
418453
const rowContext = useContext(TableRowContext);
419454
let tdView;
@@ -443,7 +478,7 @@ function TableCellView(props: {
443478
radius: columnStyle.radius || columnsStyle.radius,
444479
borderWidth: columnStyle.borderWidth || columnsStyle.borderWidth,
445480
textSize: columnStyle.textSize || columnsStyle.textSize,
446-
height: rowHeight,
481+
rowHeight: rowHeight,
447482
}
448483
let { background } = style;
449484
if (rowContext.selected) {
@@ -458,6 +493,8 @@ function TableCellView(props: {
458493
background={background}
459494
$style={style}
460495
$isEditing={editing}
496+
$tableSize={tableSize}
497+
$autoHeight={autoHeight}
461498
>
462499
{children}
463500
</TableTd>
@@ -530,6 +567,8 @@ function ResizeableTable<RecordType extends object>(props: CustomTableProps<Reco
530567
rowIndex: rowIndex,
531568
columnsStyle: props.columnsStyle,
532569
columnStyle: style,
570+
tableSize: props.size,
571+
autoHeight: props.rowAutoHeight,
533572
}),
534573
onHeaderCell: () => ({
535574
width: resizeWidth,
@@ -598,6 +637,7 @@ export function TableCompView(props: {
598637
const compChildren = comp.children;
599638
const style = compChildren.style.getView();
600639
const rowStyle = compChildren.rowStyle.getView();
640+
const rowAutoHeight = compChildren.rowAutoHeight.getView();
601641
const columnsStyle = compChildren.columnsStyle.getView();
602642
const changeSet = useMemo(() => compChildren.columns.getChangeSet(), [compChildren.columns]);
603643
const hasChange = useMemo(() => !_.isEmpty(changeSet), [changeSet]);
@@ -625,7 +665,7 @@ export function TableCompView(props: {
625665
size,
626666
dynamicColumn,
627667
dynamicColumnConfig,
628-
columnsAggrData
668+
columnsAggrData,
629669
),
630670
[
631671
columnViews,
@@ -738,6 +778,7 @@ export function TableCompView(props: {
738778
viewModeResizable={compChildren.viewModeResizable.getView()}
739779
dataSource={pageDataInfo.data}
740780
size={compChildren.size.getView()}
781+
rowAutoHeight={rowAutoHeight}
741782
tableLayout="fixed"
742783
loading={
743784
loading ||

client/packages/lowcoder/src/comps/comps/tableComp/tablePropertyView.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -504,13 +504,13 @@ export function compTablePropertyView<T extends MultiBaseComp<TableChildrenType>
504504

505505
{["layout", "both"].includes(editorModeStatus) && (
506506
<><Section name={"Table Style"}>
507-
{comp.children.style.getPropertyView()}
508-
507+
{comp.children.style.getPropertyView()}
509508
</Section>
510509
<Section name={"Row Style"}>
511510
{comp.children.rowStyle.getPropertyView()}
512-
{comp.children.rowColor.getPropertyView()}
511+
{comp.children.rowAutoHeight.getPropertyView()}
513512
{comp.children.rowHeight.getPropertyView()}
513+
{comp.children.rowColor.getPropertyView()}
514514
</Section>
515515
<Section name={"Column Style"}>
516516
{comp.children.columnsStyle.getPropertyView()}

client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ const tableChildrenMap = {
190190
onEvent: TableEventControl,
191191
loading: BoolCodeControl,
192192
rowColor: RowColorComp,
193+
rowAutoHeight: withDefault(AutoHeightControl, "auto"),
193194
rowHeight: RowHeightComp,
194195
dynamicColumn: BoolPureControl,
195196
// todo: support object config

client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ export function columnsToAntdFormat(
267267
size: string,
268268
dynamicColumn: boolean,
269269
dynamicColumnConfig: Array<string>,
270-
columnsAggrData: ColumnsAggrData
270+
columnsAggrData: ColumnsAggrData,
271271
): Array<CustomColumnType<RecordType>> {
272272
const sortMap: Map<string | undefined, SortOrder> = new Map(
273273
sort.map((s) => [s.column, s.desc ? "descend" : "ascend"])
@@ -338,7 +338,12 @@ export function columnsToAntdFormat(
338338
String(record[OB_ROW_ORI_INDEX])
339339
)
340340
.getView()
341-
.view({ editable: column.editable, size, candidateTags: tags, candidateStatus: status });
341+
.view({
342+
editable: column.editable,
343+
size, candidateTags: tags,
344+
candidateStatus: status,
345+
textOverflow: column.textOverflow,
346+
});
342347
},
343348
...(column.sortable
344349
? {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { trans } from "i18n";
2+
import { ControlParams } from "./controlParams";
3+
import { dropdownAbstractControl } from "./dropdownControl";
4+
5+
const overflowOptions = [
6+
{
7+
label: "Ellipsis", // trans("autoHeightProp.auto"),
8+
value: "ellipsis",
9+
},
10+
{
11+
label: "Wrap", // trans("autoHeightProp.fixed"),
12+
value: "wrap",
13+
},
14+
] as const;
15+
16+
const TextOverflowTmpControl = dropdownAbstractControl(overflowOptions, "ellipsis");
17+
export class TextOverflowControl extends TextOverflowTmpControl {
18+
override getView() {
19+
return this.value !== "ellipsis";
20+
}
21+
22+
override getPropertyView() {
23+
return this.propertyView({ label: "Text Overflow"/*trans("prop.height")*/ });
24+
}
25+
26+
override propertyView(params: ControlParams) {
27+
return super.propertyView({ radioButton: true, ...params });
28+
}
29+
}

0 commit comments

Comments
 (0)