@@ -10,7 +10,15 @@ import {
10
10
SpaceProps ,
11
11
BorderProps
12
12
} from 'styled-system' ;
13
- import { FC , PropsWithChildren } from 'react' ;
13
+ import {
14
+ FC ,
15
+ PropsWithChildren ,
16
+ RefAttributes ,
17
+ useRef ,
18
+ useState ,
19
+ HTMLAttributes
20
+ } from 'react' ;
21
+ import useResizeObserver from 'use-resize-observer' ;
14
22
15
23
const decoration = system ( { textDecoration : true } ) ;
16
24
type DecorationProps = Pick < CSSObject , 'textDecoration' > ;
@@ -113,6 +121,54 @@ ListItem.defaultProps = {
113
121
margin : 0
114
122
} ;
115
123
124
+ const FitContainer = styled . div `
125
+ width: 100%;
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ ` ;
130
+
131
+ const ScalableText = styled (
132
+ Text as FC < CommonTypographyProps & RefAttributes < HTMLDivElement > >
133
+ ) < { scale : number } > `
134
+ transform-origin: center;
135
+ transform: scale(${ ( props ) => props . scale } );
136
+ white-space: nowrap;
137
+ ` ;
138
+ ScalableText . defaultProps = {
139
+ ...Text . defaultProps ,
140
+ textAlign : 'center' ,
141
+ scale : 1
142
+ } ;
143
+
144
+ const FitText : FC <
145
+ PropsWithChildren < CommonTypographyProps & HTMLAttributes < HTMLDivElement > >
146
+ > = ( props ) => {
147
+ const containerRef = useRef < HTMLDivElement > ( null ) ;
148
+ const textRef = useRef < HTMLDivElement > ( null ) ;
149
+ const [ scale , setScale ] = useState ( 1 ) ;
150
+
151
+ useResizeObserver ( {
152
+ ref : containerRef ,
153
+ onResize : ( ) => {
154
+ if ( ! containerRef . current || ! textRef . current ) return ;
155
+
156
+ const containerWidth = containerRef . current . offsetWidth ;
157
+ const textWidth = textRef . current . offsetWidth ;
158
+ if ( textWidth === 0 ) return ;
159
+
160
+ const newScale = Math . min ( containerWidth / textWidth ) ;
161
+ setScale ( newScale ) ;
162
+ }
163
+ } ) ;
164
+
165
+ return (
166
+ < FitContainer ref = { containerRef } >
167
+ < ScalableText { ...props } ref = { textRef } scale = { scale } />
168
+ </ FitContainer >
169
+ ) ;
170
+ } ;
171
+
116
172
export {
117
173
Text ,
118
174
Heading ,
@@ -121,5 +177,6 @@ export {
121
177
UnorderedList ,
122
178
ListItem ,
123
179
Link ,
124
- CodeSpan
180
+ CodeSpan ,
181
+ FitText
125
182
} ;
0 commit comments