55import {
66 BlockGrayLabel ,
77 ControlPropertyViewWrapper ,
8+ CustomModal ,
89 DeleteInputIcon ,
910 TacoButton ,
1011 TacoInput ,
@@ -25,6 +26,9 @@ import { getBase64 } from "@lowcoder-ee/util/fileUtils";
2526import Flex from "antd/es/flex" ;
2627import Typography from "antd/es/typography" ;
2728import LoadingOutlined from "@ant-design/icons/LoadingOutlined" ;
29+ import Badge from "antd/es/badge" ;
30+ import { CrownFilled } from "@ant-design/icons" ;
31+ import { SUBSCRIPTION_SETTING } from "@lowcoder-ee/constants/routesURL" ;
2832
2933const ButtonWrapper = styled . div `
3034 width: 100%;
@@ -125,7 +129,7 @@ const IconList = styled(List)`
125129` ;
126130
127131const IconRow = styled . div `
128- padding: 0 6px;
132+ padding: 6px;
129133 display: flex;
130134 align-items: flex-start; /* Align items to the start to allow different heights */
131135 justify-content: space-between;
@@ -134,37 +138,56 @@ const IconRow = styled.div`
134138 gap: 8px;
135139 justify-content: flex-start;
136140 }
141+
142+ .ant-badge {
143+ height: 100%;
144+ }
137145` ;
138146
139147const IconItemContainer = styled . div `
140148 width: 60px;
149+ height: 60px;
141150 display: flex;
142151 flex-direction: column;
143152 align-items: center;
144153 justify-content: flex-start;
145154 cursor: pointer;
146155 font-size: 28px;
147- margin-bottom: 24px;
156+ border-radius: 4px;
157+ background: #fafafa;
148158
149159 &:hover {
150- border: 1px solid #315efb;
151- border-radius: 4px;
160+ box-shadow: 0 8px 24px #1a29470a,0 2px 8px #1a294714;
152161 }
153162
154163 &:focus {
155164 border: 1px solid #315efb;
156- border-radius: 4px;
157165 box-shadow: 0 0 0 2px #d6e4ff;
158166 }
159167` ;
160168
161- const IconWrapper = styled . div `
162- height: auto ;
169+ const IconWrapper = styled . div < { $isPremium ?: boolean } > `
170+ height: 100% ;
163171 display: flex;
164172 align-items: center;
165173 justify-content: center;
174+ ${ props => props . $isPremium && 'opacity: 0.25' } ;
175+ ` ;
176+
177+ const StyledPreviewIcon = styled . img `
178+ width: auto;
179+ height: auto;
180+ max-width: 100%;
181+ max-height: 100%;
166182` ;
167183
184+ const StyledPreviewLotte = styled . video `
185+ width: auto;
186+ height: auto;
187+ max-width: 100%;
188+ max-height: 100%;
189+ `
190+
168191export enum AssetType {
169192 ICON = "icon" ,
170193 ILLUSTRATION = "illustration" ,
@@ -182,9 +205,8 @@ const IconScoutSearchParams: SearchParams = {
182205 query : '' ,
183206 product_type : 'item' ,
184207 asset : 'icon' ,
185- per_page : 50 ,
208+ per_page : 25 ,
186209 page : 1 ,
187- formats : 'svg' ,
188210 sort : 'relevant' ,
189211} ;
190212
@@ -216,13 +238,20 @@ export const IconPicker = (props: {
216238
217239 const fetchResults = async ( query : string ) => {
218240 setLoading ( true ) ;
219- const result = await IconscoutApi . search ( {
241+ const freeResult = await IconscoutApi . search ( {
220242 ...IconScoutSearchParams ,
221243 asset : props . assetType ,
244+ price : 'free' ,
245+ query,
246+ } ) ;
247+ const premiumResult = await IconscoutApi . search ( {
248+ ...IconScoutSearchParams ,
249+ asset : props . assetType ,
250+ price : 'premium' ,
222251 query,
223252 } ) ;
224253 setLoading ( false ) ;
225- setSearchResults ( result . data ) ;
254+ setSearchResults ( [ ... freeResult . data , ... premiumResult . data ] ) ;
226255 } ;
227256
228257 const downloadAsset = async (
@@ -271,33 +300,53 @@ export const IconPicker = (props: {
271300 key = { icon . uuid }
272301 tabIndex = { 0 }
273302 onClick = { ( ) => {
303+ // check if premium content then show subscription popup
304+ // TODO: if user has subscription then skip this if block
305+ if ( icon . price !== 0 ) {
306+ CustomModal . confirm ( {
307+ title : trans ( "iconScout.buySubscriptionTitle" ) ,
308+ content : trans ( "iconScout.buySubscriptionContent" ) ,
309+ onConfirm : ( ) => {
310+ window . open ( SUBSCRIPTION_SETTING , "_blank" ) ;
311+ } ,
312+ confirmBtnType : "primary" ,
313+ okText : trans ( "iconScout.buySubscriptionButton" ) ,
314+ } )
315+ return ;
316+ }
317+
274318 fetchDownloadUrl (
275319 icon . uuid ,
276320 props . assetType === AssetType . ICON ? icon . urls . png_64 : icon . urls . thumb ,
277321 ) ;
278322 } }
279323 >
280- < IconWrapper >
281- { props . assetType === AssetType . ICON && (
282- < img style = { { 'width' : '100%' } } src = { icon . urls . png_64 } />
283- ) }
284- { props . assetType === AssetType . ILLUSTRATION && (
285- < img style = { { 'width' : '100%' } } src = { icon . urls . thumb } />
286- ) }
287- { props . assetType === AssetType . LOTTIE && (
288- < video style = { { 'width' : '100%' } } src = { icon . urls . thumb } autoPlay />
289- ) }
290- </ IconWrapper >
324+ < Badge
325+ count = { icon . price !== 0 ? < CrownFilled style = { { color : "#e7b549" } } /> : undefined }
326+ size = 'small'
327+ >
328+ < IconWrapper $isPremium = { icon . price !== 0 } >
329+ { props . assetType === AssetType . ICON && (
330+ < StyledPreviewIcon src = { icon . urls . png_64 } />
331+ ) }
332+ { props . assetType === AssetType . ILLUSTRATION && (
333+ < StyledPreviewIcon src = { icon . urls . thumb } />
334+ ) }
335+ { props . assetType === AssetType . LOTTIE && (
336+ < StyledPreviewLotte src = { icon . urls . thumb } autoPlay />
337+ ) }
338+ </ IconWrapper >
339+ </ Badge >
291340 </ IconItemContainer >
292341 ) ) }
293342 </ IconRow >
294343 ) , [ searchResults ]
295344 ) ;
296345
297346 const popupTitle = useMemo ( ( ) => {
298- if ( props . assetType === AssetType . ILLUSTRATION ) return 'Search Image' ;
299- if ( props . assetType === AssetType . LOTTIE ) return 'Search Animation' ;
300- return 'Search Icon' ;
347+ if ( props . assetType === AssetType . ILLUSTRATION ) return trans ( "iconScout.searchImage" ) ;
348+ if ( props . assetType === AssetType . LOTTIE ) return trans ( "iconScout.searchAnimation" ) ;
349+ return trans ( "iconScout.searchIcon" ) ;
301350 } , [ props . assetType ] ) ;
302351
303352 return (
@@ -337,7 +386,7 @@ export const IconPicker = (props: {
337386 { ! loading && Boolean ( searchText ) && ! searchResults ?. length && (
338387 < Flex align = "center" justify = "center" style = { { flex : 1 } } >
339388 < Typography . Text type = "secondary" >
340- No results found.
389+ { trans ( "iconScout.noResults" ) }
341390 </ Typography . Text >
342391 </ Flex >
343392 ) }
0 commit comments