@@ -45,6 +45,12 @@ export interface AdjustLabelFitProps {
4545 */
4646 maxFontWidth ?: number
4747
48+ /**
49+ * Enable letter spacing adjustment to fit text
50+ * Default is false
51+ */
52+ useLetterSpacing ?: boolean
53+
4854 /**
4955 * Minimum letter spacing in pixels
5056 * Default is -1px
@@ -84,8 +90,9 @@ export const AdjustLabelFit: React.FC<AdjustLabelFitProps> = ({
8490 fontSize,
8591 minFontWidth = 50 ,
8692 maxFontWidth = 120 ,
87- defaultOpticalSize = 40 ,
93+ defaultOpticalSize = 120 ,
8894 defaultWidth = 100 ,
95+ useLetterSpacing = false ,
8996 minLetterSpacing = - 1 ,
9097 containerStyle = { } ,
9198 labelStyle = { } ,
@@ -145,7 +152,6 @@ export const AdjustLabelFit: React.FC<AdjustLabelFitProps> = ({
145152
146153 // Apply the new width setting
147154 labelElement . style . fontVariationSettings = `'opsz' ${ defaultOpticalSize } , 'wdth' ${ defaultWidth } `
148-
149155 // Reset label content if it was cut
150156 labelElement . textContent = label
151157
@@ -163,65 +169,62 @@ export const AdjustLabelFit: React.FC<AdjustLabelFitProps> = ({
163169 void labelElement . offsetWidth
164170
165171 const containerWidth = containerElement . clientWidth
166- // Remeasure after font size adjustment
167- void labelElement . offsetWidth
168172 const newTextWidth = labelElement . getBoundingClientRect ( ) . width
169173
170174 // If text now fits with font size adjustment alone, we're done
171175 if ( newTextWidth <= containerWidth ) return
172176
173177 const widthRatio = containerWidth / newTextWidth
174178 let currentWidth = defaultWidth * widthRatio
175- const currentOpticalSize = 100 - defaultOpticalSize * widthRatio
176179
177180 // Use a reasonable range for width variation
178181 currentWidth = Math . max ( currentWidth , minFontWidth )
179182 currentWidth = Math . min ( currentWidth , maxFontWidth )
180183
181- labelElement . style . fontVariationSettings = `'opsz' ${ currentOpticalSize } , 'wdth' ${ currentWidth } `
184+ labelElement . style . fontVariationSettings = `'opsz' ${ defaultOpticalSize } , 'wdth' ${ currentWidth } `
182185
183186 // Remeasure text width after adjustment:
184187 void labelElement . offsetWidth
185188 const adjustedTextWidth = labelElement . getBoundingClientRect ( ) . width
186189
187190 // Letter spacing if text still overflows
188- if ( adjustedTextWidth > containerWidth ) {
191+ if ( useLetterSpacing && adjustedTextWidth > containerWidth ) {
189192 const overflow = adjustedTextWidth - containerWidth
190193 const letterCount = label . length - 1 // Spaces between letters
191194 let letterSpacing = letterCount > 0 ? - overflow / letterCount : 0
192195
193196 letterSpacing = Math . max ( letterSpacing , minLetterSpacing )
194197 labelElement . style . letterSpacing = `${ letterSpacing } px`
198+ }
195199
196- // Hard cut text if enabled and letterspacing is not enough:
197- if ( hardCutText ) {
198- void labelElement . offsetWidth
199- const finalTextWidth = labelElement . getBoundingClientRect ( ) . width
200- if ( finalTextWidth > containerWidth ) {
201- const ratio = containerWidth / finalTextWidth
202- const visibleChars = Math . floor ( label . length * ratio ) - 1
203- labelElement . textContent = label . slice ( 0 , Math . max ( visibleChars , 1 ) )
204- }
205- } else {
206- // Apply line wrapping per letter if hardCutText is not set
207- void labelElement . offsetWidth
208- const finalTextWidth = labelElement . getBoundingClientRect ( ) . width
209- if ( finalTextWidth > containerWidth ) {
210- labelElement . textContent = ''
211-
212- for ( let i = 0 ; i < label . length ; i ++ ) {
213- const charSpan = document . createElement ( 'span' )
214- charSpan . textContent = label [ i ]
215- charSpan . style . display = 'inline-block'
216- charSpan . style . wordBreak = 'break-all'
217- charSpan . style . whiteSpace = 'normal'
218- labelElement . appendChild ( charSpan )
219- }
220-
221- // Apply wrapping styles
222- labelElement . style . wordBreak = 'break-all'
223- labelElement . style . whiteSpace = 'normal'
200+ // Hard cut text or wrap per letter:
201+ if ( hardCutText ) {
202+ void labelElement . offsetWidth
203+ const finalTextWidth = labelElement . getBoundingClientRect ( ) . width
204+ if ( finalTextWidth > containerWidth ) {
205+ const ratio = containerWidth / finalTextWidth
206+ const visibleChars = Math . floor ( label . length * ratio ) - 1
207+ labelElement . textContent = label . slice ( 0 , Math . max ( visibleChars , 1 ) )
208+ }
209+ } else {
210+ // Apply line wrapping per letter if hardCutText is not set
211+ void labelElement . offsetWidth
212+ const finalTextWidth = labelElement . getBoundingClientRect ( ) . width
213+ if ( finalTextWidth > containerWidth ) {
214+ labelElement . textContent = ''
215+
216+ for ( let i = 0 ; i < label . length ; i ++ ) {
217+ const charSpan = document . createElement ( 'span' )
218+ charSpan . textContent = label [ i ]
219+ charSpan . style . display = 'inline-block'
220+ charSpan . style . wordBreak = 'break-all'
221+ charSpan . style . whiteSpace = 'normal'
222+ labelElement . appendChild ( charSpan )
224223 }
224+
225+ // Apply wrapping styles
226+ labelElement . style . wordBreak = 'break-all'
227+ labelElement . style . whiteSpace = 'normal'
225228 }
226229 }
227230 }
0 commit comments