import { Box, chakra, Flex } from '@chakra-ui/react'; import type { IconProps } from '@chakra-ui/react'; import React from 'react'; import type { ExternalChain } from 'types/externalChains'; import type { ImageProps } from 'toolkit/chakra/image'; import { Image } from 'toolkit/chakra/image'; import type { LinkProps } from 'toolkit/chakra/link'; import { Link as LinkToolkit } from 'toolkit/chakra/link'; import { Skeleton } from 'toolkit/chakra/skeleton'; import { Tooltip } from 'toolkit/chakra/tooltip'; import { TruncatedText } from 'toolkit/components/truncation/TruncatedText'; import type { Props as CopyToClipboardProps } from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard'; import HashStringShorten from 'ui/shared/HashStringShorten'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import type { Props as IconSvgProps } from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg'; import { getContentProps, getIconProps } from './utils'; export type Truncation = 'constant' | 'constant_long' | 'dynamic' | 'tail' | 'none'; export type Variant = 'content' | 'heading' | 'subheading'; export interface EntityBaseProps { className?: string; href?: string; icon?: EntityIconProps; link?: LinkProps; isLoading?: boolean; noTooltip?: boolean; noCopy?: boolean; noIcon?: boolean; noLink?: boolean; onClick?: (event: React.MouseEvent) => void; query?: Record; tailLength?: number; target?: React.HTMLAttributeAnchorTarget; truncation?: Truncation; truncationMaxSymbols?: number; variant?: Variant; chain?: ExternalChain; } export interface ContainerBaseProps extends Pick { children: React.ReactNode; onMouseEnter?: (event: React.MouseEvent) => void; onMouseLeave?: (event: React.MouseEvent) => void; } const Container = chakra(({ className, children, ...props }: ContainerBaseProps) => { return ( { children } ); }); export interface LinkBaseProps extends Pick { children: React.ReactNode; variant?: LinkProps['variant']; noIcon?: LinkProps['noIcon']; external?: LinkProps['external']; } const Link = chakra(({ isLoading, children, external, onClick, href, noLink, variant, noIcon }: LinkBaseProps) => { const styles = { display: 'inline-flex', alignItems: 'center', minWidth: 0, // for content truncation - https://css-tricks.com/flexbox-truncated-text/ }; if (noLink) { return null; } return ( { children } ); }); type EntityIconProps = (ImageProps | IconSvgProps) & Pick & { shield?: IconShieldProps | false; hint?: string; hintPostfix?: string; tooltipInteractive?: boolean; size?: number; // for AddressIdenticon in address entity }; export type IconBaseProps = Pick & EntityIconProps; const Icon = (props: IconBaseProps) => { const { isLoading, noIcon, variant, color, borderRadius, marginRight, boxSize, shield, hint, tooltipInteractive, ...rest } = props; if (noIcon) { return null; } const styles = getIconProps(props, Boolean(shield)); const iconElement = (() => { const commonProps = { marginRight: styles.marginRight, boxSize: boxSize ?? styles.boxSize, borderRadius: borderRadius ?? 'base', flexShrink: 0, minW: 0, }; if (isLoading) { return ; } if ('src' in props) { return ; } const svgProps = rest as IconSvgProps; return ( ); })(); const content = ( { iconElement } { shield && } ); if (!hint) { return content; } return ( { content } ); }; type IconShieldProps = (ImageProps | IconSvgProps) & { isLoading?: boolean; variant?: Variant }; const IconShield = (props: IconShieldProps) => { const { variant, ...rest } = props; const styles = { position: 'absolute', top: variant === 'heading' ? '14px' : '6px', left: variant === 'heading' ? '18px' : '12px', boxSize: '18px', borderRadius: 'full', borderWidth: '1px', borderStyle: 'solid', // The colors can be changed on hover, if address is highlighted // Because the highlighted styles are described as CSS classes, we must do the same for the shield border color. // borderColor: 'bg.primary', // backgroundColor: 'bg.primary', className: 'entity__shield', }; if ('src' in rest) { return rest.isLoading ? : ; } const svgProps = rest as IconSvgProps; return ; }; export interface ContentBaseProps extends Pick< EntityBaseProps, 'className' | 'isLoading' | 'truncation' | 'tailLength' | 'noTooltip' | 'variant' | 'truncationMaxSymbols' | 'noLink' > { asProp?: React.ElementType; text: string; tooltipInteractive?: boolean; } const Content = chakra(({ className, isLoading, asProp, text, truncation = 'dynamic', truncationMaxSymbols, tailLength, variant, noTooltip, tooltipInteractive, noLink, }: ContentBaseProps) => { const styles = getContentProps(variant); if (truncation === 'tail') { return ( ); } const children = (() => { switch (truncation) { case 'constant_long': return ( ); case 'constant': return ( ); case 'dynamic': return ( ); case 'none': return { text }; } })(); return ( { children } ); }); export type CopyBaseProps = Pick & Pick ; const Copy = ({ noCopy, ...props }: CopyBaseProps) => { if (noCopy) { return null; } return ; }; export { Container, Link, Icon, IconShield, Copy, Content, };