@@ -10,15 +10,61 @@ import { ComponentRegistry } from '@object-ui/core';
1010import type { IconSchema } from '@object-ui/types' ;
1111import { icons } from 'lucide-react' ;
1212import React , { forwardRef } from 'react' ;
13+ import { cn } from '../../lib/utils' ;
14+
15+ // Convert kebab-case to PascalCase for Lucide icon names
16+ // e.g., "arrow-right" -> "ArrowRight", "home" -> "Home"
17+ function toPascalCase ( str : string ) : string {
18+ return str
19+ . split ( '-' )
20+ . map ( word => word . charAt ( 0 ) . toUpperCase ( ) + word . slice ( 1 ) )
21+ . join ( '' ) ;
22+ }
1323
1424const IconRenderer = forwardRef < SVGSVGElement , { schema : IconSchema ; className ?: string ; [ key : string ] : any } > (
1525 ( { schema, className, ...props } , ref ) => {
16- const Icon = ( icons as any ) [ schema . name || schema . icon ] ;
17- if ( ! Icon ) return null ;
18- return < Icon ref = { ref } className = { className } { ...props } /> ;
26+ // Extract designer-related props
27+ const {
28+ 'data-obj-id' : dataObjId ,
29+ 'data-obj-type' : dataObjType ,
30+ style,
31+ ...iconProps
32+ } = props ;
33+
34+ // Convert icon name to PascalCase for Lucide lookup
35+ const iconName = toPascalCase ( schema . name ) ;
36+ const Icon = ( icons as any ) [ iconName ] ;
37+
38+ if ( ! Icon ) {
39+ console . warn ( `Icon "${ schema . name } " (lookup: "${ iconName } ") not found in lucide-react` ) ;
40+ return null ;
41+ }
42+
43+ // Build size style
44+ const sizeStyle = schema . size ? { width : schema . size , height : schema . size } : undefined ;
45+
46+ // Merge classNames: schema color, schema className, prop className
47+ const mergedClassName = cn (
48+ schema . color ,
49+ schema . className ,
50+ className
51+ ) ;
52+
53+ return (
54+ < Icon
55+ ref = { ref }
56+ className = { mergedClassName }
57+ style = { { ...sizeStyle , ...style } }
58+ { ...iconProps }
59+ // Apply designer props
60+ { ...{ 'data-obj-id' : dataObjId , 'data-obj-type' : dataObjType } }
61+ />
62+ ) ;
1963 }
2064) ;
2165
66+ IconRenderer . displayName = 'IconRenderer' ;
67+
2268ComponentRegistry . register ( 'icon' ,
2369 IconRenderer ,
2470 {
@@ -27,6 +73,8 @@ ComponentRegistry.register('icon',
2773 category : 'basic' ,
2874 inputs : [
2975 { name : 'name' , type : 'string' , label : 'Icon Name' , defaultValue : 'smile' } ,
76+ { name : 'size' , type : 'number' , label : 'Size (px)' } ,
77+ { name : 'color' , type : 'string' , label : 'Color Class' } ,
3078 { name : 'className' , type : 'string' , label : 'CSS Class' }
3179 ]
3280 }
0 commit comments