Commit 78c8fd23 authored by Jack Short's avatar Jack Short Committed by GitHub

style: updating cards to use appropriate aspect ratio (#5681)

* style: updating cards to use appropriate aspect ratio

* loading card height

* audio and video cards

* change loading height rendering

* respond to self serving comments
Co-authored-by: default avatarCharles Bachmeier <charlie@genie.xyz>
parent c3787529
...@@ -16,7 +16,7 @@ import { ...@@ -16,7 +16,7 @@ import {
import { body, bodySmall, buttonTextMedium, subhead } from 'nft/css/common.css' import { body, bodySmall, buttonTextMedium, subhead } from 'nft/css/common.css'
import { themeVars } from 'nft/css/sprinkles.css' import { themeVars } from 'nft/css/sprinkles.css'
import { useIsMobile } from 'nft/hooks' import { useIsMobile } from 'nft/hooks'
import { GenieAsset, Rarity, TokenType, WalletAsset } from 'nft/types' import { GenieAsset, Rarity, TokenType, UniformAspectRatio, UniformAspectRatios, WalletAsset } from 'nft/types'
import { fallbackProvider, isAudio, isVideo, putCommas } from 'nft/utils' import { fallbackProvider, isAudio, isVideo, putCommas } from 'nft/utils'
import { floorFormatter } from 'nft/utils/numbers' import { floorFormatter } from 'nft/utils/numbers'
import { import {
...@@ -240,16 +240,62 @@ const ImageContainer = ({ children, isDisabled = false }: { children: ReactNode; ...@@ -240,16 +240,62 @@ const ImageContainer = ({ children, isDisabled = false }: { children: ReactNode;
<StyledImageContainer isDisabled={isDisabled}>{children}</StyledImageContainer> <StyledImageContainer isDisabled={isDisabled}>{children}</StyledImageContainer>
) )
/* -------- CARD IMAGE -------- */ const handleUniformAspectRatio = (
uniformAspectRatio: UniformAspectRatio,
e: React.SyntheticEvent<HTMLElement, Event>,
setUniformAspectRatio?: (uniformAspectRatio: UniformAspectRatio) => void,
renderedHeight?: number,
setRenderedHeight?: (renderedHeight: number | undefined) => void
) => {
if (uniformAspectRatio !== UniformAspectRatios.square && setUniformAspectRatio) {
const height = e.currentTarget.clientHeight
const width = e.currentTarget.clientWidth
const aspectRatio = width / height
if (
(!renderedHeight || renderedHeight !== height) &&
aspectRatio < 1 &&
uniformAspectRatio !== UniformAspectRatios.square &&
setRenderedHeight
) {
setRenderedHeight(height)
}
if (uniformAspectRatio === UniformAspectRatios.unset) {
setUniformAspectRatio(aspectRatio >= 1 ? UniformAspectRatios.square : aspectRatio)
} else if (uniformAspectRatio !== aspectRatio) {
setUniformAspectRatio(UniformAspectRatios.square)
setRenderedHeight && setRenderedHeight(undefined)
}
}
}
function getHeightFromAspectRatio(uniformAspectRatio: UniformAspectRatio, renderedHeight?: number): number | undefined {
return uniformAspectRatio === UniformAspectRatios.square || uniformAspectRatio === UniformAspectRatios.unset
? undefined
: renderedHeight
}
interface ImageProps {
uniformAspectRatio?: UniformAspectRatio
setUniformAspectRatio?: (uniformAspectRatio: UniformAspectRatio) => void
renderedHeight?: number
setRenderedHeight?: (renderedHeight: number | undefined) => void
}
const Image = () => { const Image = ({
uniformAspectRatio = UniformAspectRatios.square,
setUniformAspectRatio,
renderedHeight,
setRenderedHeight,
}: ImageProps) => {
const { hovered, asset } = useCardContext() const { hovered, asset } = useCardContext()
const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl) const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl)
const [loaded, setLoaded] = useState(false) const [loaded, setLoaded] = useState(false)
const isMobile = useIsMobile() const isMobile = useIsMobile()
if (noContent) { if (noContent) {
return <NoContentContainer /> return <NoContentContainer height={getHeightFromAspectRatio(uniformAspectRatio, renderedHeight)} />
} }
return ( return (
...@@ -258,7 +304,7 @@ const Image = () => { ...@@ -258,7 +304,7 @@ const Image = () => {
as="img" as="img"
width="full" width="full"
style={{ style={{
aspectRatio: '1', aspectRatio: `${uniformAspectRatio === UniformAspectRatios.square || !setUniformAspectRatio ? '1' : 'auto'}`,
transition: 'transform 0.25s ease 0s', transition: 'transform 0.25s ease 0s',
}} }}
src={asset.imageUrl || asset.smallImageUrl} src={asset.imageUrl || asset.smallImageUrl}
...@@ -266,6 +312,7 @@ const Image = () => { ...@@ -266,6 +312,7 @@ const Image = () => {
draggable={false} draggable={false}
onError={() => setNoContent(true)} onError={() => setNoContent(true)}
onLoad={(e) => { onLoad={(e) => {
handleUniformAspectRatio(uniformAspectRatio, e, setUniformAspectRatio, renderedHeight, setRenderedHeight)
setLoaded(true) setLoaded(true)
}} }}
className={clsx(hovered && !isMobile && styles.cardImageHover, !loaded && styles.loadingBackground)} className={clsx(hovered && !isMobile && styles.cardImageHover, !loaded && styles.loadingBackground)}
...@@ -274,12 +321,26 @@ const Image = () => { ...@@ -274,12 +321,26 @@ const Image = () => {
) )
} }
function getMediaAspectRatio(
uniformAspectRatio: UniformAspectRatio,
setUniformAspectRatio?: (uniformAspectRatio: UniformAspectRatio) => void
): string {
return uniformAspectRatio === UniformAspectRatios.square || !setUniformAspectRatio ? '1' : 'auto'
}
interface MediaProps { interface MediaProps {
shouldPlay: boolean shouldPlay: boolean
setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void
} }
const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { const Video = ({
uniformAspectRatio = UniformAspectRatios.square,
setUniformAspectRatio,
renderedHeight,
setRenderedHeight,
shouldPlay,
setCurrentTokenPlayingMedia,
}: MediaProps & ImageProps) => {
const vidRef = useRef<HTMLVideoElement>(null) const vidRef = useRef<HTMLVideoElement>(null)
const { hovered, asset } = useCardContext() const { hovered, asset } = useCardContext()
const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl) const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl)
...@@ -293,7 +354,7 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { ...@@ -293,7 +354,7 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => {
} }
if (noContent) { if (noContent) {
return <NoContentContainer /> return <NoContentContainer height={getHeightFromAspectRatio(uniformAspectRatio, renderedHeight)} />
} }
return ( return (
...@@ -304,7 +365,7 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { ...@@ -304,7 +365,7 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => {
alt={asset.name || asset.tokenId} alt={asset.name || asset.tokenId}
width="full" width="full"
style={{ style={{
aspectRatio: '1', aspectRatio: getMediaAspectRatio(uniformAspectRatio, setUniformAspectRatio),
transition: 'transform 0.25s ease 0s', transition: 'transform 0.25s ease 0s',
willChange: 'transform', willChange: 'transform',
}} }}
...@@ -312,7 +373,8 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { ...@@ -312,7 +373,8 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => {
objectFit="contain" objectFit="contain"
draggable={false} draggable={false}
onError={() => setNoContent(true)} onError={() => setNoContent(true)}
onLoad={() => { onLoad={(e) => {
handleUniformAspectRatio(uniformAspectRatio, e, setUniformAspectRatio, renderedHeight, setRenderedHeight)
setImageLoaded(true) setImageLoaded(true)
}} }}
visibility={shouldPlay ? 'hidden' : 'visible'} visibility={shouldPlay ? 'hidden' : 'visible'}
...@@ -339,7 +401,9 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { ...@@ -339,7 +401,9 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => {
ref={vidRef} ref={vidRef}
width="full" width="full"
style={{ style={{
aspectRatio: '1', aspectRatio: `${
uniformAspectRatio === UniformAspectRatios.square || !setUniformAspectRatio ? '1' : 'auto'
}`,
}} }}
onEnded={(e) => { onEnded={(e) => {
e.preventDefault() e.preventDefault()
...@@ -372,7 +436,14 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { ...@@ -372,7 +436,14 @@ const Video = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => {
) )
} }
const Audio = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { const Audio = ({
uniformAspectRatio = UniformAspectRatios.square,
setUniformAspectRatio,
renderedHeight,
setRenderedHeight,
shouldPlay,
setCurrentTokenPlayingMedia,
}: MediaProps & ImageProps) => {
const audRef = useRef<HTMLAudioElement>(null) const audRef = useRef<HTMLAudioElement>(null)
const { hovered, asset } = useCardContext() const { hovered, asset } = useCardContext()
const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl) const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl)
...@@ -386,7 +457,7 @@ const Audio = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { ...@@ -386,7 +457,7 @@ const Audio = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => {
} }
if (noContent) { if (noContent) {
return <NoContentContainer /> return <NoContentContainer height={getHeightFromAspectRatio(uniformAspectRatio, renderedHeight)} />
} }
return ( return (
...@@ -397,7 +468,7 @@ const Audio = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { ...@@ -397,7 +468,7 @@ const Audio = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => {
alt={asset.name || asset.tokenId} alt={asset.name || asset.tokenId}
width="full" width="full"
style={{ style={{
aspectRatio: '1', aspectRatio: getMediaAspectRatio(uniformAspectRatio, setUniformAspectRatio),
transition: 'transform 0.4s ease 0s', transition: 'transform 0.4s ease 0s',
}} }}
src={asset.imageUrl || asset.smallImageUrl} src={asset.imageUrl || asset.smallImageUrl}
...@@ -405,6 +476,7 @@ const Audio = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => { ...@@ -405,6 +476,7 @@ const Audio = ({ shouldPlay, setCurrentTokenPlayingMedia }: MediaProps) => {
draggable={false} draggable={false}
onError={() => setNoContent(true)} onError={() => setNoContent(true)}
onLoad={(e) => { onLoad={(e) => {
handleUniformAspectRatio(uniformAspectRatio, e, setUniformAspectRatio, renderedHeight, setRenderedHeight)
setImageLoaded(true) setImageLoaded(true)
}} }}
className={clsx(hovered && !isMobile && styles.cardImageHover, !imageLoaded && styles.loadingBackground)} className={clsx(hovered && !isMobile && styles.cardImageHover, !imageLoaded && styles.loadingBackground)}
...@@ -729,12 +801,13 @@ const Pool = () => { ...@@ -729,12 +801,13 @@ const Pool = () => {
) )
} }
const NoContentContainer = () => ( const NoContentContainer = ({ height }: { height?: number }) => (
<> <>
<Box <Box
position="relative" position="relative"
width="full" width="full"
style={{ style={{
height: height ? `${height}px` : 'auto',
paddingTop: '100%', paddingTop: '100%',
background: `linear-gradient(90deg, ${themeVars.colors.backgroundSurface} 0%, ${themeVars.colors.backgroundInteractive} 95.83%)`, background: `linear-gradient(90deg, ${themeVars.colors.backgroundSurface} 0%, ${themeVars.colors.backgroundInteractive} 95.83%)`,
}} }}
......
...@@ -7,7 +7,7 @@ import Tooltip from 'components/Tooltip' ...@@ -7,7 +7,7 @@ import Tooltip from 'components/Tooltip'
import { Box } from 'nft/components/Box' import { Box } from 'nft/components/Box'
import { bodySmall } from 'nft/css/common.css' import { bodySmall } from 'nft/css/common.css'
import { useBag } from 'nft/hooks' import { useBag } from 'nft/hooks'
import { GenieAsset, isPooledMarket, TokenType } from 'nft/types' import { GenieAsset, isPooledMarket, TokenType, UniformAspectRatio } from 'nft/types'
import { formatWeiToDecimal, rarityProviderLogo } from 'nft/utils' import { formatWeiToDecimal, rarityProviderLogo } from 'nft/utils'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
...@@ -22,6 +22,10 @@ interface CollectionAssetProps { ...@@ -22,6 +22,10 @@ interface CollectionAssetProps {
mediaShouldBePlaying: boolean mediaShouldBePlaying: boolean
setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void
rarityVerified?: boolean rarityVerified?: boolean
uniformAspectRatio: UniformAspectRatio
setUniformAspectRatio: (uniformAspectRatio: UniformAspectRatio) => void
renderedHeight?: number
setRenderedHeight: (renderedHeight: number | undefined) => void
} }
const TOOLTIP_TIMEOUT = 2000 const TOOLTIP_TIMEOUT = 2000
...@@ -43,6 +47,10 @@ export const CollectionAsset = ({ ...@@ -43,6 +47,10 @@ export const CollectionAsset = ({
mediaShouldBePlaying, mediaShouldBePlaying,
setCurrentTokenPlayingMedia, setCurrentTokenPlayingMedia,
rarityVerified, rarityVerified,
uniformAspectRatio,
setUniformAspectRatio,
renderedHeight,
setRenderedHeight,
}: CollectionAssetProps) => { }: CollectionAssetProps) => {
const bagManuallyClosed = useBag((state) => state.bagManuallyClosed) const bagManuallyClosed = useBag((state) => state.bagManuallyClosed)
const addAssetsToBag = useBag((state) => state.addAssetsToBag) const addAssetsToBag = useBag((state) => state.addAssetsToBag)
...@@ -161,11 +169,30 @@ export const CollectionAsset = ({ ...@@ -161,11 +169,30 @@ export const CollectionAsset = ({
timeout={isMobile ? TOOLTIP_TIMEOUT : undefined} timeout={isMobile ? TOOLTIP_TIMEOUT : undefined}
> >
{assetMediaType === AssetMediaType.Image ? ( {assetMediaType === AssetMediaType.Image ? (
<Card.Image /> <Card.Image
uniformAspectRatio={uniformAspectRatio}
setUniformAspectRatio={setUniformAspectRatio}
renderedHeight={renderedHeight}
setRenderedHeight={setRenderedHeight}
/>
) : assetMediaType === AssetMediaType.Video ? ( ) : assetMediaType === AssetMediaType.Video ? (
<Card.Video shouldPlay={mediaShouldBePlaying} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} /> <Card.Video
shouldPlay={mediaShouldBePlaying}
setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia}
uniformAspectRatio={uniformAspectRatio}
setUniformAspectRatio={setUniformAspectRatio}
renderedHeight={renderedHeight}
setRenderedHeight={setRenderedHeight}
/>
) : ( ) : (
<Card.Audio shouldPlay={mediaShouldBePlaying} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} /> <Card.Audio
shouldPlay={mediaShouldBePlaying}
setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia}
uniformAspectRatio={uniformAspectRatio}
setUniformAspectRatio={setUniformAspectRatio}
renderedHeight={renderedHeight}
setRenderedHeight={setRenderedHeight}
/>
)} )}
</MouseoverTooltip> </MouseoverTooltip>
</Card.ImageContainer> </Card.ImageContainer>
......
...@@ -35,7 +35,16 @@ import { ...@@ -35,7 +35,16 @@ import {
} from 'nft/hooks' } from 'nft/hooks'
import { useIsCollectionLoading } from 'nft/hooks/useIsCollectionLoading' import { useIsCollectionLoading } from 'nft/hooks/useIsCollectionLoading'
import { usePriceRange } from 'nft/hooks/usePriceRange' import { usePriceRange } from 'nft/hooks/usePriceRange'
import { DropDownOption, GenieAsset, GenieCollection, isPooledMarket, Markets, TokenType } from 'nft/types' import {
DropDownOption,
GenieAsset,
GenieCollection,
isPooledMarket,
Markets,
TokenType,
UniformAspectRatio,
UniformAspectRatios,
} from 'nft/types'
import { import {
calcPoolPrice, calcPoolPrice,
calcSudoSwapPrice, calcSudoSwapPrice,
...@@ -169,17 +178,17 @@ const MarketNameWrapper = styled(Row)` ...@@ -169,17 +178,17 @@ const MarketNameWrapper = styled(Row)`
gap: 8px; gap: 8px;
` `
export const LoadingAssets = ({ count }: { count?: number }) => ( export const LoadingAssets = ({ count, height }: { count?: number; height?: number }) => (
<> <>
{Array.from(Array(count ?? ASSET_PAGE_SIZE), (_, index) => ( {Array.from(Array(count ?? ASSET_PAGE_SIZE), (_, index) => (
<CollectionAssetLoading key={index} /> <CollectionAssetLoading key={index} height={height} />
))} ))}
</> </>
) )
const CollectionNftsLoading = () => ( const CollectionNftsLoading = ({ height }: { height?: number }) => (
<Box width="full" className={styles.assetList}> <Box width="full" className={styles.assetList}>
<LoadingAssets /> <LoadingAssets height={height} />
</Box> </Box>
) )
...@@ -269,6 +278,9 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie ...@@ -269,6 +278,9 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
const debouncedMaxPrice = useDebounce(maxPrice, 500) const debouncedMaxPrice = useDebounce(maxPrice, 500)
const debouncedSearchByNameText = useDebounce(searchByNameText, 500) const debouncedSearchByNameText = useDebounce(searchByNameText, 500)
const [uniformAspectRatio, setUniformAspectRatio] = useState<UniformAspectRatio>(UniformAspectRatios.unset)
const [renderedHeight, setRenderedHeight] = useState<number | undefined>()
const [sweepIsOpen, setSweepOpen] = useState(false) const [sweepIsOpen, setSweepOpen] = useState(false)
// Load all sweep queries. Loading them on the parent allows lazy-loading, but avoids waterfalling requests. // Load all sweep queries. Loading them on the parent allows lazy-loading, but avoids waterfalling requests.
const collectionParams = useSweepFetcherParams(contractAddress, 'others', debouncedMinPrice, debouncedMaxPrice) const collectionParams = useSweepFetcherParams(contractAddress, 'others', debouncedMinPrice, debouncedMaxPrice)
...@@ -413,9 +425,13 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie ...@@ -413,9 +425,13 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
mediaShouldBePlaying={asset.tokenId === currentTokenPlayingMedia} mediaShouldBePlaying={asset.tokenId === currentTokenPlayingMedia}
setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia}
rarityVerified={rarityVerified} rarityVerified={rarityVerified}
uniformAspectRatio={uniformAspectRatio}
setUniformAspectRatio={setUniformAspectRatio}
renderedHeight={renderedHeight}
setRenderedHeight={setRenderedHeight}
/> />
)) ))
}, [collectionAssets, currentTokenPlayingMedia, isMobile, rarityVerified]) }, [collectionAssets, isMobile, currentTokenPlayingMedia, rarityVerified, uniformAspectRatio, renderedHeight])
const hasNfts = collectionAssets && collectionAssets.length > 0 const hasNfts = collectionAssets && collectionAssets.length > 0
const hasErc1155s = hasNfts && collectionAssets[0] && collectionAssets[0].tokenType === TokenType.ERC1155 const hasErc1155s = hasNfts && collectionAssets[0] && collectionAssets[0].tokenType === TokenType.ERC1155
...@@ -461,6 +477,11 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie ...@@ -461,6 +477,11 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [location]) }, [location])
useEffect(() => {
setUniformAspectRatio(UniformAspectRatios.unset)
setRenderedHeight(undefined)
}, [contractAddress])
useEffect(() => { useEffect(() => {
if (collectionStats && collectionStats.stats?.floor_price) { if (collectionStats && collectionStats.stats?.floor_price) {
const lowValue = collectionStats.stats?.floor_price const lowValue = collectionStats.stats?.floor_price
...@@ -601,7 +622,7 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie ...@@ -601,7 +622,7 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
<InfiniteScroll <InfiniteScroll
next={handleNextPageLoad} next={handleNextPageLoad}
hasMore={hasNext} hasMore={hasNext}
loader={Boolean(hasNext && hasNfts) && <LoadingAssets />} loader={Boolean(hasNext && hasNfts) && <LoadingAssets height={renderedHeight} />}
dataLength={collectionAssets?.length ?? 0} dataLength={collectionAssets?.length ?? 0}
style={{ overflow: 'unset' }} style={{ overflow: 'unset' }}
className={hasNfts || isLoadingNext ? styles.assetList : undefined} className={hasNfts || isLoadingNext ? styles.assetList : undefined}
...@@ -624,7 +645,7 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie ...@@ -624,7 +645,7 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
</EmptyCollectionWrapper> </EmptyCollectionWrapper>
</Center> </Center>
) : ( ) : (
<CollectionNftsLoading /> <CollectionNftsLoading height={renderedHeight} />
)} )}
</InfiniteScroll> </InfiniteScroll>
</InfiniteScrollWrapper> </InfiniteScrollWrapper>
......
...@@ -36,12 +36,12 @@ export type CollectionSort = Record< ...@@ -36,12 +36,12 @@ export type CollectionSort = Record<
'asc' | 'desc' | 1 | -1 | { $gte?: string | number; $lte?: string | number } | string | number 'asc' | 'desc' | 1 | -1 | { $gte?: string | number; $lte?: string | number } | string | number
> >
export enum UniformHeights { export enum UniformAspectRatios {
unset, unset,
notUniform, square,
} }
export type UniformHeight = UniformHeights | number export type UniformAspectRatio = UniformAspectRatios | number
export enum ActivityEventType { export enum ActivityEventType {
Listing = 'LISTING', Listing = 'LISTING',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment