From 0f042717ab573327f28466ab29c9a1cb8be7fd7f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 05:06:22 +0000 Subject: [PATCH 1/2] Initial plan From 20d320e9dcf8358cd38041658d93f0a5dcc27592 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 05:12:37 +0000 Subject: [PATCH 2/2] Add Icon widget component with lucide-react integration Co-authored-by: foreleven <4785594+foreleven@users.noreply.github.com> --- .../src/components/widget-components/icon.tsx | 78 +++++++++++++++++++ .../src/components/widget-components/index.ts | 3 + 2 files changed, 81 insertions(+) create mode 100644 apps/widget-builder/src/components/widget-components/icon.tsx diff --git a/apps/widget-builder/src/components/widget-components/icon.tsx b/apps/widget-builder/src/components/widget-components/icon.tsx new file mode 100644 index 0000000..0c7f4a0 --- /dev/null +++ b/apps/widget-builder/src/components/widget-components/icon.tsx @@ -0,0 +1,78 @@ +import * as LucideIcons from "lucide-react"; +import { ComponentDefinition } from "monaco-jsx-editor"; +import React from "react"; + +import { cn } from "@/lib/utils"; + +export interface IconProps extends React.HTMLAttributes { + name: string; + color?: string; + size?: number | string; +} + +const Icon = React.forwardRef(({ name, color, size = 24, className, ...props }, ref) => { + // Get the icon component from lucide-react + // Convert kebab-case or snake_case to PascalCase for icon lookup + const iconName = name + .split(/[-_\s]/) + .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(""); + + const IconComponent = (LucideIcons as Record>)[iconName]; + + if (!IconComponent) { + // Return a placeholder if icon not found + return ( + + + + + + ); + } + + return ; +}); +Icon.displayName = "Icon"; + +const IconDefinition: ComponentDefinition = { + name: "Icon", + description: "An icon component that maps to icons from the lucide-react library.", + props: [ + { + name: "name", + type: "string", + required: true, + description: + "The name of the icon from lucide-react (e.g., 'Home', 'User', 'Settings', 'Search'). Supports PascalCase, kebab-case, or snake_case.", + }, + { + name: "color", + type: "string", + description: "The color of the icon. Can be any valid CSS color value.", + }, + { + name: "size", + type: "number | string", + defaultValue: "24", + description: "The size of the icon in pixels.", + }, + ], + category: "Display", + usage: ``, +}; + +export { Icon, IconDefinition }; diff --git a/apps/widget-builder/src/components/widget-components/index.ts b/apps/widget-builder/src/components/widget-components/index.ts index 63869ab..3e3c0ef 100644 --- a/apps/widget-builder/src/components/widget-components/index.ts +++ b/apps/widget-builder/src/components/widget-components/index.ts @@ -8,6 +8,7 @@ import { Caption, CaptionDefinition } from "./caption"; import { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent, CardDefinition } from "./card"; import { Col, ColDefinition } from "./col"; import { Divider, DividerDefinition } from "./divider"; +import { Icon, IconDefinition } from "./icon"; import { Image, ImageDefinition } from "./image"; import { Progress, ProgressDefinition } from "./progress"; import { Row, RowDefinition } from "./row"; @@ -45,6 +46,7 @@ export const components: ComponentMap = { Divider, Spacer, Badge, + Icon, Image, Progress, }; @@ -65,6 +67,7 @@ export const definitions: ComponentDefinition[] = [ DividerDefinition, SpacerDefinition, BadgeDefinition, + IconDefinition, ImageDefinition, ProgressDefinition, ];