22
33from reflex .components .component import Component
44from reflex .utils import format
5- from reflex .vars .base import Var
5+ from reflex .utils .imports import ImportVar
6+ from reflex .vars .base import LiteralVar , Var
7+ from reflex .vars .sequence import LiteralStringVar
68
79
810class LucideIconComponent (Component ):
911 """Lucide Icon Component."""
1012
11- library = "lucide-react@0.469.0 "
13+ library = "lucide-react@0.471.1 "
1214
1315
1416class Icon (LucideIconComponent ):
@@ -32,39 +34,61 @@ def create(cls, *children, **props) -> Component:
3234 Raises:
3335 AttributeError: The errors tied to bad usage of the Icon component.
3436 ValueError: If the icon tag is invalid.
37+ TypeError: If the icon name is not a string.
3538
3639 Returns:
3740 The created component.
3841 """
3942 if children :
4043 if len (children ) == 1 and isinstance (children [0 ], str ):
4144 props ["tag" ] = children [0 ]
42- children = []
4345 else :
4446 raise AttributeError (
4547 f"Passing multiple children to Icon component is not allowed: remove positional arguments { children [1 :]} to fix"
4648 )
4749 if "tag" not in props :
4850 raise AttributeError ("Missing 'tag' keyword-argument for Icon" )
4951
52+ tag : str | Var | LiteralVar = props .pop ("tag" )
53+ if isinstance (tag , LiteralVar ):
54+ if isinstance (tag , LiteralStringVar ):
55+ tag = tag ._var_value
56+ else :
57+ raise TypeError (f"Icon name must be a string, got { type (tag )} " )
58+ elif isinstance (tag , Var ):
59+ return DynamicIcon .create (name = tag , ** props )
60+
5061 if (
51- not isinstance (props [ " tag" ] , str )
52- or format .to_snake_case (props [ " tag" ] ) not in LUCIDE_ICON_LIST
62+ not isinstance (tag , str )
63+ or format .to_snake_case (tag ) not in LUCIDE_ICON_LIST
5364 ):
5465 raise ValueError (
55- f"Invalid icon tag: { props [ ' tag' ] } . Please use one of the following: { ', ' .join (LUCIDE_ICON_LIST [0 :25 ])} , ..."
66+ f"Invalid icon tag: { tag } . Please use one of the following: { ', ' .join (LUCIDE_ICON_LIST [0 :25 ])} , ..."
5667 "\n See full list at https://lucide.dev/icons."
5768 )
5869
59- if props [ " tag" ] in LUCIDE_ICON_MAPPING_OVERRIDE :
60- props ["tag" ] = LUCIDE_ICON_MAPPING_OVERRIDE [props [ " tag" ] ]
70+ if tag in LUCIDE_ICON_MAPPING_OVERRIDE :
71+ props ["tag" ] = LUCIDE_ICON_MAPPING_OVERRIDE [tag ]
6172 else :
62- props ["tag" ] = (
63- format .to_title_case (format .to_snake_case (props ["tag" ])) + "Icon"
64- )
73+ props ["tag" ] = format .to_title_case (format .to_snake_case (tag )) + "Icon"
6574 props ["alias" ] = f"Lucide{ props ['tag' ]} "
6675 props .setdefault ("color" , "var(--current-color)" )
67- return super ().create (* children , ** props )
76+ return super ().create (** props )
77+
78+
79+ class DynamicIcon (LucideIconComponent ):
80+ """A DynamicIcon component."""
81+
82+ tag = "DynamicIcon"
83+
84+ name : Var [str ]
85+
86+ def _get_imports (self ):
87+ _imports = super ()._get_imports ()
88+ if self .library :
89+ _imports .pop (self .library )
90+ _imports ["lucide-react/dynamic" ] = [ImportVar ("DynamicIcon" , install = False )]
91+ return _imports
6892
6993
7094LUCIDE_ICON_LIST = [
@@ -846,6 +870,7 @@ def create(cls, *children, **props) -> Component:
846870 "house" ,
847871 "house_plug" ,
848872 "house_plus" ,
873+ "house_wifi" ,
849874 "ice_cream_bowl" ,
850875 "ice_cream_cone" ,
851876 "id_card" ,
@@ -1534,6 +1559,7 @@ def create(cls, *children, **props) -> Component:
15341559 "trending_up_down" ,
15351560 "triangle" ,
15361561 "triangle_alert" ,
1562+ "triangle_dashed" ,
15371563 "triangle_right" ,
15381564 "trophy" ,
15391565 "truck" ,
0 commit comments