From ad1e272794f7caca2268240e3238afee0a43fa8d Mon Sep 17 00:00:00 2001 From: Eugene Chybisov Date: Wed, 1 Jun 2022 20:46:47 +0200 Subject: [PATCH] feat: add text fitter --- packages/widget/src/components/StepToken.tsx | 28 ++++--- .../src/components/SwapRoutes/SwapRoutes.tsx | 2 +- .../src/components/TextFitter/TextFitter.tsx | 79 +++++++++++++++++++ .../widget/src/components/TextFitter/index.ts | 1 + .../widget/src/components/TextFitter/types.ts | 13 +++ 5 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 packages/widget/src/components/TextFitter/TextFitter.tsx create mode 100644 packages/widget/src/components/TextFitter/index.ts create mode 100644 packages/widget/src/components/TextFitter/types.ts diff --git a/packages/widget/src/components/StepToken.tsx b/packages/widget/src/components/StepToken.tsx index 17f5bb89a..ae7ba4363 100644 --- a/packages/widget/src/components/StepToken.tsx +++ b/packages/widget/src/components/StepToken.tsx @@ -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 ( - - - {token.symbol[0]} - - - {formatTokenAmount(token.amount, token.decimals)} - + + + + {token.symbol[0]} + + + {formatTokenAmount(token.amount, token.decimals)} + + {token.symbol} diff --git a/packages/widget/src/components/SwapRoutes/SwapRoutes.tsx b/packages/widget/src/components/SwapRoutes/SwapRoutes.tsx index ad727fcc4..3bbae2cdf 100644 --- a/packages/widget/src/components/SwapRoutes/SwapRoutes.tsx +++ b/packages/widget/src/components/SwapRoutes/SwapRoutes.tsx @@ -41,7 +41,7 @@ export const SwapRoutes: React.FC = (props) => { ({ borderRadius: theme.shape.borderRadiusSecondary / theme.shape.borderRadius, diff --git a/packages/widget/src/components/TextFitter/TextFitter.tsx b/packages/widget/src/components/TextFitter/TextFitter.tsx new file mode 100644 index 000000000..d1f84f30b --- /dev/null +++ b/packages/widget/src/components/TextFitter/TextFitter.tsx @@ -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> = ({ + children, + width = '100%', + height, + maxHeight, + preserveAspectRatio = 'xMinYMid meet', + textStyle, + svgStyle, + cropTop, + cropBottom, + onFit, +}) => { + const textRef = useRef(null); + const [viewBox, setViewBox] = useState>(initialState); + const [textRect, setTextRect] = useState>(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 ( + = maxHeight + ? maxHeight + : height + } + preserveAspectRatio={preserveAspectRatio} + > + + {children} + + + ); +}; diff --git a/packages/widget/src/components/TextFitter/index.ts b/packages/widget/src/components/TextFitter/index.ts new file mode 100644 index 000000000..f91aee43d --- /dev/null +++ b/packages/widget/src/components/TextFitter/index.ts @@ -0,0 +1 @@ +export * from './TextFitter'; diff --git a/packages/widget/src/components/TextFitter/types.ts b/packages/widget/src/components/TextFitter/types.ts new file mode 100644 index 000000000..6d5061150 --- /dev/null +++ b/packages/widget/src/components/TextFitter/types.ts @@ -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; +}