Skip to content

Commit

Permalink
feat: add text fitter
Browse files Browse the repository at this point in the history
  • Loading branch information
chybisov committed Jun 1, 2022
1 parent 1810084 commit ad1e272
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 11 deletions.
28 changes: 18 additions & 10 deletions packages/widget/src/components/StepToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,34 @@
import { TokenAmount } from '@lifinance/sdk';
import { Avatar, Box, BoxProps, Typography } from '@mui/material';
import { formatTokenAmount } from '../utils/format';
import { TextFitter } from './TextFitter';

export const StepToken: React.FC<{ token: TokenAmount } & BoxProps> = ({
token,
...other
}) => {
return (
<Box sx={{ display: 'flex', alignItems: 'center' }} {...other}>
<Avatar src={token.logoURI} alt={token.symbol} sx={{ marginRight: 2 }}>
{token.symbol[0]}
</Avatar>
<Typography fontSize={24} fontWeight="700" lineHeight={1.333334}>
{formatTokenAmount(token.amount, token.decimals)}
</Typography>
<Box flex={1} height={46} {...other}>
<Box display="flex" flex={1}>
<Avatar src={token.logoURI} alt={token.symbol} sx={{ marginRight: 2 }}>
{token.symbol[0]}
</Avatar>
<TextFitter
maxHeight={32}
textStyle={{
fontWeight: 700,
}}
>
{formatTokenAmount(token.amount, token.decimals)}
</TextFitter>
</Box>
<Typography
fontSize={14}
lineHeight={1.8577}
lineHeight={1}
fontWeight="500"
alignSelf="flex-end"
color="text.secondary"
mx={1}
mr={1}
ml={6}
>
{token.symbol}
</Typography>
Expand Down
2 changes: 1 addition & 1 deletion packages/widget/src/components/SwapRoutes/SwapRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const SwapRoutes: React.FC<BoxProps> = (props) => {
<Skeleton
variant="rectangular"
width="100%"
height={167}
height={181}
sx={(theme: Theme) => ({
borderRadius:
theme.shape.borderRadiusSecondary / theme.shape.borderRadius,
Expand Down
79 changes: 79 additions & 0 deletions packages/widget/src/components/TextFitter/TextFitter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
PropsWithChildren,
useCallback,
useLayoutEffect,
useRef,
useState,
} from 'react';
import { TextFitterProps } from './types';

const initialState = {
x: 0,
y: 0,
width: 0,
height: 0,
};

export const TextFitter: React.FC<PropsWithChildren<TextFitterProps>> = ({
children,
width = '100%',
height,
maxHeight,
preserveAspectRatio = 'xMinYMid meet',
textStyle,
svgStyle,
cropTop,
cropBottom,
onFit,
}) => {
const textRef = useRef<SVGTextElement>(null);
const [viewBox, setViewBox] = useState<Partial<DOMRect>>(initialState);
const [textRect, setTextRect] = useState<Partial<DOMRect>>(initialState);

const calculateBox = useCallback(() => {
if (!textRef.current) {
return;
}
const box = textRef.current.getBBox();
if (cropTop) {
box.y += box.height * cropTop;
box.height -= box.height * cropTop;
}
if (cropBottom) {
box.height -= box.height * cropBottom;
}
setViewBox(box);
setTextRect(textRef.current.getBoundingClientRect());
onFit?.();
}, [cropBottom, cropTop, onFit]);

useLayoutEffect(() => {
calculateBox();
}, [calculateBox, children]);

useLayoutEffect(() => {
if (document.fonts) {
document.fonts.ready.then(() => {
calculateBox();
});
}
}, [calculateBox]);

return (
<svg
style={svgStyle}
viewBox={`${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`}
width={width}
height={
textRect.height && maxHeight && textRect.height >= maxHeight
? maxHeight
: height
}
preserveAspectRatio={preserveAspectRatio}
>
<text x={0} y={0} style={textStyle} ref={textRef}>
{children}
</text>
</svg>
);
};
1 change: 1 addition & 0 deletions packages/widget/src/components/TextFitter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './TextFitter';
13 changes: 13 additions & 0 deletions packages/widget/src/components/TextFitter/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { CSSProperties } from 'react';

export interface TextFitterProps {
textStyle?: CSSProperties;
svgStyle?: CSSProperties;
onFit?(): void;
maxHeight?: string | number;
height?: string | number;
width?: string | number;
preserveAspectRatio?: string;
cropTop?: number;
cropBottom?: number;
}

0 comments on commit ad1e272

Please sign in to comment.