Skip to content

Commit d52feb5

Browse files
committed
mind column.width, check if fonts are ready
1 parent 402787c commit d52feb5

File tree

4 files changed

+66
-14
lines changed

4 files changed

+66
-14
lines changed

packages/main/src/components/AnalyticalTable/hooks/useDynamicColumnWidths.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ interface IColumnMeta {
1212
contentPxAvg: number;
1313
headerPx: number;
1414
headerDefinesWidth?: boolean;
15-
maxWidth?: number;
15+
maxWidth?: number | undefined;
16+
width?: number | undefined;
1617
}
1718

1819
const ROW_SAMPLE_SIZE = 20;
@@ -260,6 +261,7 @@ const calculateSmartAndGrowColumns = (
260261
contentPxAvg: contentPxLength,
261262
// When Grow mode is active, static max width should be applied
262263
maxWidth: column.maxWidth ?? (isGrow ? MAX_WIDTH : undefined),
264+
width: column.width,
263265
};
264266
return metadata;
265267
},
@@ -279,7 +281,7 @@ const calculateSmartAndGrowColumns = (
279281
if (isGrow) {
280282
totalContentPxAvgPrio1 += columnMeta[columnIdOrAccessor].contentPxAvg;
281283
const targetWidth = Math.min(
282-
Math.max(column.minWidth ?? 0, column.width ?? 0, contentPxAvg, headerPx),
284+
Math.max(column.minWidth ?? 0, column.width ?? Math.max(contentPxAvg, headerPx)),
283285
column.maxWidth ?? MAX_WIDTH,
284286
);
285287

@@ -288,6 +290,7 @@ const calculateSmartAndGrowColumns = (
288290
}
289291
return acc + targetWidth;
290292
}
293+
291294
if (contentPxAvg > headerPx) {
292295
if (!column.minWidth && !column.width) {
293296
totalContentPxAvgPrio1 += columnMeta[columnIdOrAccessor].contentPxAvg;
@@ -300,7 +303,7 @@ const calculateSmartAndGrowColumns = (
300303
if (!column.minWidth && !column.width) {
301304
totalNumberColPrio2++;
302305
}
303-
const max = Math.max(column.minWidth || 0, column.width || 0, headerPx);
306+
const max = Math.max(column.minWidth || 0, column.width ?? headerPx);
304307
columnMeta[columnIdOrAccessor].headerDefinesWidth = true;
305308
return acc + max;
306309
}
@@ -365,8 +368,8 @@ const calculateSmartAndGrowColumns = (
365368
width: targetWidth,
366369
};
367370
} else {
368-
const targetWidth = Math.max(column.width || 0, 60, headerPx, column.minWidth ?? 0);
369-
if (targetWidth < (column.maxWidth ?? Infinity)) {
371+
const targetWidth = Math.max(Math.min(column.width ?? 0, headerPx), column.minWidth ?? 0);
372+
if (targetWidth < (column.maxWidth ?? Infinity) && !meta.width) {
370373
lessThanMaxWidthCount++;
371374
}
372375
fullWidthOfAllColumns += targetWidth;
@@ -378,11 +381,24 @@ const calculateSmartAndGrowColumns = (
378381
});
379382

380383
// Step 3: Distribute remaining width to all columns that are not at their maxWidth
381-
const remainingWidth = totalWidth - fullWidthOfAllColumns;
384+
let remainingWidth = totalWidth - fullWidthOfAllColumns;
382385
if (remainingWidth > 0) {
383386
return visibleColumnsAdaptedPrio2.map((column) => {
384-
if (column.width !== column.maxWidth) {
385-
return { ...column, width: column.width + remainingWidth / lessThanMaxWidthCount };
387+
const columnIdOrAccessor = (column.id ?? column.accessor) as string;
388+
const meta = columnMeta[columnIdOrAccessor];
389+
if (column.width !== column.maxWidth && !meta.width) {
390+
const proportionalRemainingWidth = remainingWidth / (lessThanMaxWidthCount || 1);
391+
let proportionalWidth = column.width + proportionalRemainingWidth;
392+
// if maxWidth is reached, distribute the remaining width to the other columns
393+
if (proportionalWidth > column.maxWidth) {
394+
proportionalWidth = column.maxWidth;
395+
remainingWidth -= proportionalWidth - column.width;
396+
if (lessThanMaxWidthCount >= 2) {
397+
lessThanMaxWidthCount -= 1;
398+
}
399+
}
400+
401+
return { ...column, width: proportionalWidth };
386402
}
387403
return column;
388404
});
@@ -422,16 +438,17 @@ const useColumnsDeps = (
422438
state.hiddenColumns.length,
423439
webComponentsReactProperties.scaleWidthMode,
424440
isLoadingPlaceholder,
441+
webComponentsReactProperties.fontsReady,
425442
];
426443
};
427444

428445
const columns = (columns: TableInstance['columns'], { instance }: { instance: TableInstance }) => {
429-
if (!instance.state || !instance.rows) {
430-
return columns;
431-
}
446+
const { scaleWidthMode, loading, fontsReady } = instance.webComponentsReactProperties;
432447
const { state } = instance;
433448
const { hiddenColumns, tableClientWidth: totalWidth } = state;
434-
const { scaleWidthMode, loading } = instance.webComponentsReactProperties;
449+
if (!instance.state || !instance.rows || !fontsReady) {
450+
return columns;
451+
}
435452

436453
if (columns.length === 0 || !totalWidth || !AnalyticalTableScaleWidthMode[scaleWidthMode]) {
437454
return columns;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useState, useEffect } from 'react';
2+
3+
// If reused, think about implementing the behavior via useSyncExternalStore
4+
5+
/**
6+
* Hook that returns whether the fonts are loaded and ready to use.
7+
*
8+
* @returns boolean
9+
*/
10+
export function useFontsReady(): boolean {
11+
const [fontsReady, setFontsReady] = useState(document.fonts?.status === 'loaded');
12+
useEffect(() => {
13+
if (!document.fonts) return;
14+
15+
if (document.fonts.status === 'loading') {
16+
let mounted = true;
17+
18+
void document.fonts.ready.then(() => {
19+
if (mounted) {
20+
setFontsReady(true);
21+
}
22+
});
23+
24+
return () => {
25+
mounted = false;
26+
};
27+
}
28+
}, []);
29+
30+
return fontsReady;
31+
}

packages/main/src/components/AnalyticalTable/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import { useAutoResize } from './hooks/useAutoResize.js';
6262
import { useColumnsDeps } from './hooks/useColumnsDeps.js';
6363
import { useColumnDragAndDrop } from './hooks/useDragAndDrop.js';
6464
import { useDynamicColumnWidths } from './hooks/useDynamicColumnWidths.js';
65+
import { useFontsReady } from './hooks/useFontsReady.js';
6566
import { useKeyboardNavigation } from './hooks/useKeyboardNavigation.js';
6667
import { usePopIn } from './hooks/usePopIn.js';
6768
import { useResizeColumnsConfig } from './hooks/useResizeColumnsConfig.js';
@@ -186,6 +187,7 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
186187

187188
useStylesheet(styleData, AnalyticalTable.displayName);
188189
const isInitialized = useRef(false);
190+
const fontsReady = useFontsReady();
189191

190192
const nativeScrollbar = className?.includes('ui5-content-native-scrollbars');
191193
const alwaysShowSubComponent =
@@ -251,6 +253,7 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
251253
alternateRowColor,
252254
alwaysShowSubComponent,
253255
classes: classNames,
256+
fontsReady,
254257
highlightField,
255258
isTreeTable,
256259
loading,

packages/main/src/components/AnalyticalTable/types/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ export interface TableInstance {
211211
}
212212

213213
export interface WCRPropertiesType {
214+
fontsReady: boolean;
214215
selectionMode: AnalyticalTablePropTypes['selectionMode'];
215216
onRowSelect?: AnalyticalTablePropTypes['onRowSelect'];
216217
translatableTexts: {
@@ -852,10 +853,10 @@ export interface AnalyticalTablePropTypes extends Omit<CommonProps, 'title'> {
852853
*
853854
* - **Default**: The available space of the table is distributed evenly for columns without fixed width. If the minimum width of all columns is reached, horizontal scrolling will be enabled.
854855
* - **Smart**: Every column gets the space it needs for displaying the full header text. If all header texts need more space than the available table width, horizontal scrolling will be enabled. If there is space left, columns with a long text will get more space until there is no more table space left.
855-
* - **Grow**: Every column gets the space it needs for displaying its full header text and full text content of all cells. If it requires more space than the table has, horizontal scrolling will be enabled. To prevent huge header text from polluting the table, a max-width of 700px is applied to each column. It can be overwritten by setting the respective column property. This mode adds a calculated `minWidth` to each column. If the internally calculated `minWidth` is larger than the `width` set in the column options, it can lead to an unwanted scrollbar. To prevent this, you can set the `minWidth` in the column options yourself.
856+
* - **Grow**: Every column gets the space it needs for displaying its full header text and full text content of all cells. If it requires more space than the table has, horizontal scrolling will be enabled. To prevent huge header text from polluting the table, a max-width of 700px is applied to each column. It can be overwritten by setting the respective column property.
856857
*
857858
* __Note:__
858-
* - Custom cells with components instead of text as children are ignored by the `Smart` and `Grow` modes.
859+
* - Custom cells with components instead of text as children are ignored by the `Smart` and `Grow` modes. You can use the `scaleWidthModeOptions` property on the column definition to add custom strings for the internal width calculation.
859860
* - For performance reasons, the `Smart` and `Grow` modes base their calculation for table cell width on a subset of column cells. If the first 20 cells of a column are significantly smaller than the rest of the column cells, the content may still not be fully displayed for all cells.
860861
* - Only the default mode is available out of the box for the `sap.m.Table`; similar behavior to the `"Grow"` mode can be achieved in `sap.ui.table` using `autoResizeColumn`.
861862
*

0 commit comments

Comments
 (0)