@@ -20,43 +20,79 @@ const ROW_SAMPLE_SIZE = 20;
2020const MAX_WIDTH = 700 ;
2121export const CELL_PADDING_PX = 18 ; /* padding left and right 0.5rem each (16px) + borders (1px) + buffer (1px) */
2222
23- function getContentPxLongest ( rowSample : RowType [ ] , columnIdOrAccessor : string , uniqueId ) {
23+ let measurementCanvas : HTMLCanvasElement | null = null ;
24+ let measurementContext : CanvasRenderingContext2D | null = null ;
25+
26+ function getComputedCSSVarValue ( variableName : string , fallback : string ) : string {
27+ if ( typeof document === 'undefined' ) {
28+ return fallback ;
29+ }
30+ const value = getComputedStyle ( document . documentElement ) . getPropertyValue ( variableName ) ;
31+ return value . trim ( ) || fallback ;
32+ }
33+
34+ /**
35+ * Convert fontSize string to number. Only handles `rem` and `px` values as `em` is not by design.
36+ */
37+ function toPx ( fontSize : string ) : number {
38+ if ( fontSize . endsWith ( 'rem' ) ) {
39+ const rem = parseFloat ( fontSize ) ;
40+ const rootFont = parseFloat ( getComputedStyle ( document . documentElement ) . fontSize ) || 16 ;
41+ return rem * rootFont ;
42+ }
43+ if ( fontSize . endsWith ( 'px' ) ) {
44+ return parseFloat ( fontSize ) ;
45+ }
46+ return parseFloat ( fontSize ) || 16 ;
47+ }
48+
49+ function stringToPx ( dataPoint : string , isHeader : boolean = false ) : number {
50+ if ( ! measurementCanvas ) {
51+ measurementCanvas = document . createElement ( 'canvas' ) ;
52+ measurementContext = measurementCanvas . getContext ( '2d' ) ;
53+ }
54+ if ( ! measurementContext ) {
55+ return 14 * ( isHeader ? 0.55 : 0.5 ) * dataPoint . length ;
56+ }
57+
58+ const bodyFontFamily = getComputedCSSVarValue ( '--sapFontFamily' , 'Arial, Helvetica, sans-serif' ) ;
59+ const bodyFontSize = getComputedCSSVarValue ( '--sapFontSize' , '0.875rem' ) ;
60+ const headerFontFamily = getComputedCSSVarValue ( '--_ui5wcr-AnalyticalTable-HeaderFontFamily' , bodyFontFamily ) ;
61+
62+ const fontFamily = isHeader ? headerFontFamily : bodyFontFamily ;
63+ const fontSizePx = toPx ( bodyFontSize ) ;
64+
65+ measurementContext . font = `${ fontSizePx } px ${ fontFamily } ` ;
66+ return Math . ceil ( measurementContext . measureText ( dataPoint ) . width ) ;
67+ }
68+
69+ function getContentPxLongest ( rowSample : RowType [ ] , columnIdOrAccessor : string ) {
2470 return rowSample . reduce ( ( max , item ) => {
2571 const dataPoint = item . values ?. [ columnIdOrAccessor ] ;
2672
2773 if ( dataPoint ) {
28- const val = stringToPx ( dataPoint , uniqueId ) + CELL_PADDING_PX ;
74+ const val = stringToPx ( dataPoint ) + CELL_PADDING_PX ;
2975 return Math . max ( max , val ) ;
3076 }
3177
3278 return max ;
3379 } , 0 ) ;
3480}
3581
36- function getContentPxAvg ( rowSample , columnIdOrAccessor , uniqueId ) {
82+ function getContentPxAvg ( rowSample , columnIdOrAccessor ) {
3783 return (
3884 rowSample . reduce ( ( acc , item ) => {
3985 const dataPoint = item . values ?. [ columnIdOrAccessor ] ;
4086
4187 let val = 0 ;
4288 if ( dataPoint ) {
43- val = stringToPx ( dataPoint , uniqueId ) + CELL_PADDING_PX ;
89+ val = stringToPx ( dataPoint ) + CELL_PADDING_PX ;
4490 }
4591 return acc + val ;
4692 } , 0 ) / ( rowSample . length || 1 )
4793 ) ;
4894}
4995
50- function stringToPx ( dataPoint , id , isHeader = false ) {
51- const elementId = isHeader ? 'scaleModeHelperHeader' : 'scaleModeHelper' ;
52- const ruler = document . getElementById ( `${ elementId } -${ id } ` ) ;
53- if ( ruler ) {
54- ruler . textContent = `${ dataPoint } ` ;
55- return ruler . scrollWidth ;
56- }
57- return 0 ;
58- }
59-
6096function calculateDefaultColumnWidths ( tableWidth : number , columns : AnalyticalTableColumnDefinition [ ] ) {
6197 // Columns w/ external width property
6298 const fixed = [ ] ;
@@ -209,7 +245,7 @@ const calculateSmartAndGrowColumns = (
209245 hiddenColumns : ColumnType ,
210246 isGrow = false ,
211247) => {
212- const { rows, state, webComponentsReactProperties } = instance ;
248+ const { rows, state } = instance ;
213249 const rowSample = rows . slice ( 0 , ROW_SAMPLE_SIZE ) ;
214250 const { tableClientWidth : totalWidth } = state ;
215251
@@ -235,25 +271,18 @@ const calculateSmartAndGrowColumns = (
235271 let headerPx : number , contentPxLength : number ;
236272
237273 if ( column . scaleWidthModeOptions ?. cellString ) {
238- contentPxLength =
239- stringToPx ( column . scaleWidthModeOptions . cellString , webComponentsReactProperties . uniqueId ) + CELL_PADDING_PX ;
274+ contentPxLength = stringToPx ( column . scaleWidthModeOptions . cellString ) + CELL_PADDING_PX ;
240275 } else {
241276 contentPxLength = isGrow
242- ? getContentPxLongest ( rowSample , columnIdOrAccessor , webComponentsReactProperties . uniqueId )
243- : getContentPxAvg ( rowSample , columnIdOrAccessor , webComponentsReactProperties . uniqueId ) ;
277+ ? getContentPxLongest ( rowSample , columnIdOrAccessor )
278+ : getContentPxAvg ( rowSample , columnIdOrAccessor ) ;
244279 }
245280
246281 if ( column . scaleWidthModeOptions ?. headerString ) {
247- headerPx = Math . max (
248- stringToPx ( column . scaleWidthModeOptions . headerString , webComponentsReactProperties . uniqueId , true ) +
249- CELL_PADDING_PX ,
250- 60 ,
251- ) ;
282+ headerPx = Math . max ( stringToPx ( column . scaleWidthModeOptions . headerString , true ) + CELL_PADDING_PX , 60 ) ;
252283 } else {
253284 headerPx =
254- typeof column . Header === 'string'
255- ? Math . max ( stringToPx ( column . Header , webComponentsReactProperties . uniqueId , true ) + CELL_PADDING_PX , 60 )
256- : 60 ;
285+ typeof column . Header === 'string' ? Math . max ( stringToPx ( column . Header , true ) + CELL_PADDING_PX , 60 ) : 60 ;
257286 }
258287
259288 metadata [ columnIdOrAccessor ] = {
@@ -368,7 +397,7 @@ const calculateSmartAndGrowColumns = (
368397 width : targetWidth ,
369398 } ;
370399 } else {
371- const targetWidth = Math . max ( Math . min ( column . width ?? 0 , headerPx ) , column . minWidth ?? 0 ) ;
400+ const targetWidth = Math . max ( column . width > 0 ? column . width : headerPx , column . minWidth ?? 0 ) ;
372401 if ( targetWidth < ( column . maxWidth ?? Infinity ) && ! meta . width ) {
373402 lessThanMaxWidthCount ++ ;
374403 }
@@ -476,7 +505,6 @@ const columns = (columns: TableInstance['columns'], { instance }: { instance: Ta
476505 if ( scaleWidthMode === AnalyticalTableScaleWidthMode . Grow ) {
477506 return calculateSmartAndGrowColumns ( columns , instance , hiddenColumns , true ) ;
478507 }
479-
480508 const hasData = instance . data . length > 0 ;
481509
482510 if ( scaleWidthMode === AnalyticalTableScaleWidthMode . Default || ( ! hasData && loading ) ) {
0 commit comments