1+ import * as React from "react" ;
12import * as System from "~/components/system" ;
23import * as Styles from "~/common/styles" ;
34import * as Constants from "~/common/constants" ;
45import * as SVG from "~/common/svg" ;
56
67import LinkTag from "~/components/core/Link/LinkTag" ;
78
8- import { LoaderSpinner } from "~/components/system/components/Loaders " ;
9+ import { P3 } from "~/components/system/components/Typography " ;
910import { css } from "@emotion/react" ;
1011
1112const STYLES_CARD = css `
@@ -24,6 +25,11 @@ const STYLES_CARD = css`
2425 }
2526` ;
2627
28+ const STYLES_TAG_CONTAINER = ( theme ) => css `
29+ color : ${ theme . semantic . textGray } ;
30+ ${ Styles . HORIZONTAL_CONTAINER_CENTERED }
31+ ` ;
32+
2733const STYLES_FREEFORM_CARD = css `
2834 max-height : 90% ;
2935 max-width : 90% ;
@@ -69,12 +75,75 @@ const STYLES_BODY = css`
6975 max-width : 600px ;
7076` ;
7177
78+ const STYLES_LINK = ( theme ) => css `
79+ display : block;
80+ width : 100% ;
81+ ${ Styles . LINK }
82+ : hover small , .link_external_link {
83+ color : ${ theme . semantic . textGrayDark } ;
84+ }
85+
86+ .link_external_link {
87+ opacity : 0 ;
88+ transition : opacity 0.3s ;
89+ }
90+ : hover .link_external_link {
91+ opacity : 1 ;
92+ }
93+ ` ;
94+
95+ const STYLES_SOURCE = css `
96+ transition : color 0.4s ;
97+ max-width : 80% ;
98+ ` ;
99+
100+ const STYLES_SOURCE_LOGO = css `
101+ height : 12px ;
102+ width : 12px ;
103+ border-radius : 4px ;
104+ ` ;
105+
72106export default function LinkCard ( { file, isNFTLink } ) {
73107 const url = file . url ;
74108 const link = file . data . link ;
75109 const { image, name, body } = link ;
76110
77111 if ( isNFTLink ) {
112+ const faviconImgState = useImage ( { src : link . logo } ) ;
113+
114+ const tag = (
115+ < a
116+ css = { STYLES_LINK }
117+ href = { file . url }
118+ target = "_blank"
119+ rel = "noreferrer"
120+ style = { { position : "relative" , zIndex : 2 } }
121+ onClick = { ( e ) => e . stopPropagation ( ) }
122+ >
123+ < div css = { STYLES_TAG_CONTAINER } >
124+ { faviconImgState . error ? (
125+ < SVG . Link height = { 12 } width = { 12 } style = { { marginRight : 4 } } />
126+ ) : (
127+ < img
128+ src = { link . logo }
129+ alt = "Link source logo"
130+ style = { { marginRight : 4 } }
131+ css = { STYLES_SOURCE_LOGO }
132+ />
133+ ) }
134+ < P3 css = { STYLES_SOURCE } as = "small" color = "textGray" nbrOflines = { 1 } >
135+ { link . source }
136+ </ P3 >
137+ < SVG . ExternalLink
138+ className = "link_external_link"
139+ height = { 12 }
140+ width = { 12 }
141+ style = { { marginLeft : 4 } }
142+ />
143+ </ div >
144+ </ a >
145+ ) ;
146+
78147 return (
79148 < a
80149 css = { Styles . LINK }
@@ -87,15 +156,16 @@ export default function LinkCard({ file, isNFTLink }) {
87156 < div css = { STYLES_IMAGE_CONTAINER } >
88157 < img src = { image } css = { Styles . IMAGE_FILL } style = { { maxHeight : "calc(100vh - 200px)" } } />
89158 </ div >
90- < div css = { [ Styles . VERTICAL_CONTAINER , STYLES_TEXT_BOX ] } >
159+ < div css = { [ STYLES_TEXT_BOX ] } > { tag } </ div >
160+ { /* <div css={[Styles.VERTICAL_CONTAINER, STYLES_TEXT_BOX]}>
91161 <div css={STYLES_NAME}>
92162 <System.H3>{name}</System.H3>
93163 </div>
94164 <div css={STYLES_BODY}>
95165 <System.P1>{body}</System.P1>
96166 </div>
97167 <LinkTag url={url} fillWidth={false} style={{ color: Constants.semantic.textGray }} />
98- </ div >
168+ </div> */ }
99169 </ div >
100170 </ a >
101171 ) ;
@@ -143,3 +213,29 @@ export default function LinkCard({ file, isNFTLink }) {
143213 </div> */
144214 }
145215}
216+
217+ const useImage = ( { src, maxWidth } ) => {
218+ const [ imgState , setImgState ] = React . useState ( {
219+ loaded : false ,
220+ error : true ,
221+ overflow : false ,
222+ } ) ;
223+
224+ React . useEffect ( ( ) => {
225+ if ( ! src ) setImgState ( { error : true , loaded : true } ) ;
226+
227+ const img = new Image ( ) ;
228+ img . src = src ;
229+
230+ img . onload = ( ) => {
231+ if ( maxWidth && img . naturalWidth < maxWidth ) {
232+ setImgState ( ( prev ) => ( { ...prev , loaded : true , error : false , overflow : true } ) ) ;
233+ } else {
234+ setImgState ( { loaded : true , error : false } ) ;
235+ }
236+ } ;
237+ img . onerror = ( ) => setImgState ( { loaded : true , error : true } ) ;
238+ } , [ ] ) ;
239+
240+ return imgState ;
241+ } ;
0 commit comments