@@ -11,7 +11,7 @@ import {
1111 useIcon ,
1212 wrapperToControlItem ,
1313} from "lowcoder-design" ;
14- import { ReactNode , useCallback , useRef , useState } from "react" ;
14+ import { ReactNode , useCallback , useMemo , useRef , useState } from "react" ;
1515import styled from "styled-components" ;
1616import Popover from "antd/es/popover" ;
1717import { CloseIcon , SearchIcon } from "icons" ;
@@ -21,6 +21,7 @@ import List, { ListRowProps } from "react-virtualized/dist/es/List";
2121import { debounce } from "lodash" ;
2222import Spin from "antd/es/spin" ;
2323import { ControlParams } from "./controlParams" ;
24+ import { getBase64 } from "@lowcoder-ee/util/fileUtils" ;
2425
2526const ButtonWrapper = styled . div `
2627 width: 100%;
@@ -175,13 +176,19 @@ const IconKeyDisplay = styled.div`
175176 width: 100%; /* Ensure the container can grow */
176177` ;
177178
178- export enum IconScoutAssetType {
179+ export enum AssetType {
179180 ICON = "icon" ,
180181 ILLUSTRATION = "illustration" ,
181182 // '3D' = "3d",
182183 LOTTIE = "lottie" ,
183184}
184185
186+ export type IconScoutAsset = {
187+ uuid : string ;
188+ value : string ;
189+ preview : string ;
190+ }
191+
185192const IconScoutSearchParams : SearchParams = {
186193 query : '' ,
187194 product_type : 'item' ,
@@ -198,27 +205,26 @@ export const IconPicker = (props: {
198205 assetType : string ;
199206 uuid : string ;
200207 value : string ;
201- onChange : ( key : string , value : string ) => void ;
208+ preview : string ;
209+ onChange : ( key : string , value : string , preview : string ) => void ;
202210 label ?: ReactNode ;
203211 IconType ?: "OnlyAntd" | "All" | "default" | undefined ;
204212} ) => {
205- console . log ( props . value , props . assetType ) ;
206- const icon = useIcon ( props . value ) ;
207213 const [ visible , setVisible ] = useState ( false )
208214 const [ loading , setLoading ] = useState ( false )
209- const [ searchText , setSearchText ] = useState ( "" ) ;
210215 const [ searchResults , setSearchResults ] = useState < Array < any > > ( [ ] ) ;
216+
211217 const onChangeRef = useRef ( props . onChange ) ;
212218 onChangeRef . current = props . onChange ;
219+
213220 const onChangeIcon = useCallback (
214- ( key : string , value : string ) => {
215- onChangeRef . current ( key , value ) ;
221+ ( key : string , value : string , url : string ) => {
222+ onChangeRef . current ( key , value , url ) ;
216223 setVisible ( false ) ;
217224 } , [ ]
218225 ) ;
219226
220227 const fetchResults = async ( query : string ) => {
221- console . log ( 'query change' , query ) ;
222228 setLoading ( true ) ;
223229 const result = await IconscoutApi . search ( {
224230 ...IconScoutSearchParams ,
@@ -229,19 +235,38 @@ export const IconPicker = (props: {
229235 setSearchResults ( result . data ) ;
230236 } ;
231237
232- const fetchAsset = async ( uuid : string ) => {
238+ const downloadAsset = async (
239+ uuid : string ,
240+ downloadUrl : string ,
241+ callback : ( assetUrl : string ) => void ,
242+ ) => {
243+ try {
244+ if ( uuid && downloadUrl ) {
245+ const json = await IconscoutApi . downloadAsset ( downloadUrl ) ;
246+ getBase64 ( json , ( url : string ) => {
247+ callback ( url ) ;
248+ } ) ;
249+ }
250+ } catch ( error ) {
251+ console . error ( error ) ;
252+ }
253+ }
254+
255+ const fetchDownloadUrl = async ( uuid : string ) => {
233256 try {
234257 const result = await IconscoutApi . download ( uuid , {
235- format : 'svg' ,
258+ format : props . assetType === AssetType . LOTTIE ? 'lottie' : 'svg' ,
259+ } ) ;
260+
261+ downloadAsset ( uuid , result . download_url , ( assetUrl : string ) => {
262+ onChangeIcon ( uuid , assetUrl , result . url ) ;
236263 } ) ;
237- onChangeIcon ( result . uuid , result . url ) ;
238264 } catch ( error ) {
239265 console . error ( error ) ;
240266 }
241267 }
242268
243269 const handleChange = debounce ( ( e ) => {
244- setSearchText ( e . target . value ) ;
245270 fetchResults ( e . target . value ) ;
246271 } , 500 ) ;
247272
@@ -255,21 +280,17 @@ export const IconPicker = (props: {
255280 key = { icon . uuid }
256281 tabIndex = { 0 }
257282 onClick = { ( ) => {
258- if ( props . assetType === IconScoutAssetType . LOTTIE ) {
259- onChangeIcon ( icon . uuid , icon . urls . thumb )
260- } else {
261- fetchAsset ( icon . uuid ) ;
262- }
283+ fetchDownloadUrl ( icon . uuid ) ;
263284 } }
264285 >
265286 < IconWrapper >
266- { props . assetType === IconScoutAssetType . ICON && (
287+ { props . assetType === AssetType . ICON && (
267288 < img style = { { 'width' : '100%' } } src = { icon . urls . png_64 } />
268289 ) }
269- { props . assetType === IconScoutAssetType . ILLUSTRATION && (
290+ { props . assetType === AssetType . ILLUSTRATION && (
270291 < img style = { { 'width' : '100%' } } src = { icon . urls . thumb } />
271292 ) }
272- { props . assetType === IconScoutAssetType . LOTTIE && (
293+ { props . assetType === AssetType . LOTTIE && (
273294 < video style = { { 'width' : '100%' } } src = { icon . urls . thumb } autoPlay />
274295 ) }
275296 </ IconWrapper >
@@ -279,6 +300,12 @@ export const IconPicker = (props: {
279300 ) , [ searchResults ]
280301 ) ;
281302
303+ const popupTitle = useMemo ( ( ) => {
304+ if ( props . assetType === AssetType . ILLUSTRATION ) return 'Search Image' ;
305+ if ( props . assetType === AssetType . LOTTIE ) return 'Search Animation' ;
306+ return 'Search Icon' ;
307+ } , [ props . assetType ] ) ;
308+
282309 return (
283310 < Popover
284311 trigger = { 'click' }
@@ -288,25 +315,27 @@ export const IconPicker = (props: {
288315 onOpenChange = { setVisible }
289316 // getPopupContainer={parent ? () => parent : undefined}
290317 // hide the original background when dragging the popover is allowed
291- overlayInnerStyle = { {
292- border : "none" ,
293- boxShadow : "none" ,
294- background : "transparent" ,
295- } }
296318 // when dragging is allowed, always re-location to avoid the popover exceeds the screen
319+ styles = { {
320+ body : {
321+ border : "none" ,
322+ boxShadow : "none" ,
323+ background : "transparent" ,
324+ }
325+ } }
297326 destroyTooltipOnHide
298327 content = {
299328 < Draggable handle = ".dragHandle" >
300329 < PopupContainer >
301330 < TitleDiv className = "dragHandle" >
302- < TitleText > { "Select Icon" } </ TitleText >
331+ < TitleText > { popupTitle } </ TitleText >
303332 < StyledCloseIcon onClick = { ( ) => setVisible ( false ) } />
304333 </ TitleDiv >
305334 < SearchDiv >
306335 < TacoInput
307336 style = { { width : "100%" , paddingLeft : "40px" } }
308337 onChange = { handleChange }
309- placeholder = { "Search Icon" }
338+ placeholder = { popupTitle }
310339 />
311340 < StyledSearchIcon />
312341 </ SearchDiv >
@@ -329,19 +358,19 @@ export const IconPicker = (props: {
329358 }
330359 >
331360 < TacoButton style = { { width : "100%" } } >
332- { props . value ? (
361+ { props . preview ? (
333362 < ButtonWrapper >
334363 < ButtonIconWrapper >
335- { props . assetType === IconScoutAssetType . LOTTIE && (
336- < video style = { { 'width' : '100%' } } src = { props . value } autoPlay />
364+ { props . assetType === AssetType . LOTTIE && (
365+ < video style = { { 'width' : '100%' } } src = { props . preview } autoPlay />
337366 ) }
338- { props . assetType !== IconScoutAssetType . LOTTIE && (
339- < IconControlView value = { props . value } uuid = { props . uuid } />
367+ { props . assetType !== AssetType . LOTTIE && (
368+ < IconControlView value = { props . preview } uuid = { props . uuid } />
340369 ) }
341370 </ ButtonIconWrapper >
342371 < StyledDeleteInputIcon
343372 onClick = { ( e ) => {
344- props . onChange ( "" , "" ) ;
373+ props . onChange ( "" , "" , "" ) ;
345374 e . stopPropagation ( ) ;
346375 } }
347376 />
@@ -364,19 +393,16 @@ export function IconControlView(props: { value: string, uuid: string }) {
364393 return < StyledImage src = { value } alt = "" /> ;
365394}
366395
367- type DataType = {
368- uuid : string ;
369- value : string ;
370- }
371396export function IconscoutControl (
372- assetType : string = IconScoutAssetType . ICON ,
397+ assetType : string = AssetType . ICON ,
373398) {
374- return class IconscoutControl extends SimpleComp < DataType > {
399+ return class IconscoutControl extends SimpleComp < IconScoutAsset > {
375400 readonly IGNORABLE_DEFAULT_VALUE = false ;
376- protected getDefaultValue ( ) : DataType {
401+ protected getDefaultValue ( ) : IconScoutAsset {
377402 return {
378403 uuid : '' ,
379404 value : '' ,
405+ preview : '' ,
380406 } ;
381407 }
382408
@@ -391,8 +417,9 @@ export function IconscoutControl(
391417 assetType = { assetType }
392418 uuid = { this . value . uuid }
393419 value = { this . value . value }
394- onChange = { ( uuid , value ) => {
395- this . dispatchChangeValueAction ( { uuid, value} )
420+ preview = { this . value . preview }
421+ onChange = { ( uuid , value , preview ) => {
422+ this . dispatchChangeValueAction ( { uuid, value, preview} )
396423 } }
397424 label = { params . label }
398425 IconType = { params . IconType }
0 commit comments