refactor: Implement Lazy loading for icons in cloud deployments (#7218)

* init add lazy loading for icons

* Add more icon fixes

* [autofix.ci] apply automated fixes

* cleanup

* [autofix.ci] apply automated fixes

* add change to user management modal

* Add eager loading for common icons

* add fallback for flow id

* [autofix.ci] apply automated fixes

* ♻️ (GenericNode/index.tsx): refactor selectedNodes to selectedNodesCount for better readability and performance optimization

* add one more icon

* add missing icon

* cleanup

* [autofix.ci] apply automated fixes

* fallback fixes

* [autofix.ci] apply automated fixes

* move lucide imports

* [autofix.ci] apply automated fixes

* conditional lazy loading for cloud only

* [autofix.ci] apply automated fixes

* fix imports

* [autofix.ci] apply automated fixes

* up the shards

* add a bit of a timeout

* group icon fix and reduce playground button rerenders

* and new icons to lazy load

* [autofix.ci] apply automated fixes

* warning cleanup

* iconExists fix

* cleanup

* [autofix.ci] apply automated fixes

* move icon

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com>
Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
This commit is contained in:
Mike Fortman 2025-04-15 11:00:16 -05:00 committed by GitHub
commit ebe20e131b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 1377 additions and 889 deletions

View file

@ -1,11 +1,12 @@
import { useTypesStore } from "@/stores/typesStore";
import {
BG_NOISE,
iconExists,
nodeColors,
nodeIconsLucide,
toolModeGradient,
} from "@/utils/styleUtils";
import emojiRegex from "emoji-regex";
import { useEffect, useState } from "react";
import { ICON_STROKE_WIDTH } from "@/constants/constants";
import { checkLucideIcons } from "@/CustomNodes/helpers/check-lucide-icons";
@ -26,7 +27,14 @@ export function NodeIcon({
hasToolMode: boolean;
}) {
const types = useTypesStore((state) => state.types);
const name = nodeIconsLucide[dataType] ? dataType : types[dataType];
const [name, setName] = useState(types[dataType]);
useEffect(() => {
iconExists(dataType).then((exists) => {
setName(exists ? dataType : types[dataType]);
});
}, [dataType, types]);
const isEmoji = emojiRegex().test(icon ?? "");
const iconColor = nodeColors[types[dataType]];
const iconName = icon || (isGroup ? "group_components" : name);

View file

@ -1,11 +1,10 @@
import dynamicIconImports from "lucide-react/dynamicIconImports";
import { Suspense, forwardRef, lazy, memo } from "react";
import React, { Suspense, forwardRef, lazy, memo } from "react";
import { IconComponentProps } from "../../../types/components";
import { nodeIconsLucide } from "../../../utils/styleUtils";
import { getNodeIcon } from "../../../utils/styleUtils";
import { cn } from "../../../utils/utils";
import Loading from "../../ui/loading";
import { useEffect, useState } from "react";
import { Skeleton } from "@/components/ui/skeleton";
import { useCallback, useEffect, useState } from "react";
export const ForwardedIconComponent = memo(
forwardRef(
@ -23,28 +22,32 @@ export const ForwardedIconComponent = memo(
ref,
) => {
const [showFallback, setShowFallback] = useState(false);
const [iconError, setIconError] = useState(false);
const [TargetIcon, setTargetIcon] = useState<any>(null);
useEffect(() => {
// Reset states when icon name changes
setIconError(false);
setTargetIcon(null);
const timer = setTimeout(() => {
setShowFallback(true);
}, 30);
return () => clearTimeout(timer);
}, []);
// Load the icon if we have a name
if (name && typeof name === "string") {
getNodeIcon(name)
.then((component) => {
setTargetIcon(component);
})
.catch((error) => {
console.error(`Error loading icon ${name}:`, error);
setIconError(true);
});
}
let TargetIcon =
nodeIconsLucide[name] ||
nodeIconsLucide[
name
?.split("-")
?.map((x) => String(x[0])?.toUpperCase() + String(x).slice(1))
?.join("")
];
if (!TargetIcon) {
if (!dynamicIconImports[name]) {
TargetIcon = nodeIconsLucide["unknown"];
} else TargetIcon = lazy(dynamicIconImports[name]);
}
return () => clearTimeout(timer);
}, [name]);
const style = {
strokeWidth: strokeWidth ?? 1.5,
@ -52,13 +55,30 @@ export const ForwardedIconComponent = memo(
...(iconColor && { color: iconColor, stroke: stroke }),
};
if (!TargetIcon) {
return null; // Render nothing until the icon is loaded
// Handler for when the Suspense component throws
const handleError = useCallback(() => {
setIconError(true);
}, []);
if (!TargetIcon || iconError) {
// Return a placeholder div or null depending on settings
return skipFallback ? null : (
<div
className={cn(className, "flex items-center justify-center")}
data-testid={
dataTestId
? dataTestId
: id
? `${id}-placeholder`
: `icon-placeholder`
}
/>
);
}
const fallback = showFallback ? (
<div className={cn(className, "flex items-center justify-center")}>
<Loading />
<Skeleton className="h-4 w-4" />
</div>
) : (
<div className={className}></div>
@ -66,18 +86,34 @@ export const ForwardedIconComponent = memo(
return (
<Suspense fallback={skipFallback ? undefined : fallback}>
<TargetIcon
className={className}
style={style}
ref={ref}
data-testid={
dataTestId ? dataTestId : id ? `${id}-${name}` : `icon-${name}`
}
/>
<ErrorBoundary onError={handleError}>
<TargetIcon
className={className}
style={style}
ref={ref}
data-testid={
dataTestId ? dataTestId : id ? `${id}-${name}` : `icon-${name}`
}
/>
</ErrorBoundary>
</Suspense>
);
},
),
);
// Simple error boundary component for catching lazy load errors
class ErrorBoundary extends React.Component<{
children: React.ReactNode;
onError: () => void;
}> {
componentDidCatch(error: any) {
this.props.onError();
}
render() {
return this.props.children;
}
}
export default ForwardedIconComponent;

View file

@ -1,41 +1,54 @@
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { PLAYGROUND_BUTTON_NAME } from "@/constants/constants";
import { ENABLE_PUBLISH } from "@/customization/feature-flags";
import IOModal from "@/modals/IOModal/new-modal";
const PlaygroundButton = ({ hasIO, open, setOpen, canvasOpen }) => {
const PlayIcon = () => (
<ForwardedIconComponent
name="Play"
className="h-4 w-4 transition-all"
strokeWidth={2}
/>
);
interface PlaygroundButtonProps {
hasIO: boolean;
open: boolean;
setOpen: (open: boolean) => void;
canvasOpen: boolean;
}
const ButtonLabel = () => (
<span className="hidden md:block">{PLAYGROUND_BUTTON_NAME}</span>
);
const PlayIcon = () => (
<ForwardedIconComponent
name="Play"
className="h-4 w-4 transition-all"
strokeWidth={ENABLE_PUBLISH ? 2 : 1.5}
/>
);
const ActiveButton = () => (
<div
data-testid="playground-btn-flow-io"
className="playground-btn-flow-toolbar hover:bg-accent"
>
<PlayIcon />
<ButtonLabel />
</div>
);
const ButtonLabel = () => (
<span className="hidden md:block">{PLAYGROUND_BUTTON_NAME}</span>
);
const DisabledButton = () => (
<div
className="playground-btn-flow-toolbar cursor-not-allowed text-muted-foreground duration-150"
data-testid="playground-btn-flow"
>
<PlayIcon />
<ButtonLabel />
</div>
);
const ActiveButton = () => (
<div
data-testid="playground-btn-flow-io"
className="playground-btn-flow-toolbar hover:bg-accent"
>
<PlayIcon />
<ButtonLabel />
</div>
);
const DisabledButton = () => (
<div
className="playground-btn-flow-toolbar cursor-not-allowed text-muted-foreground duration-150"
data-testid="playground-btn-flow"
>
<PlayIcon />
<ButtonLabel />
</div>
);
const PlaygroundButton = ({
hasIO,
open,
setOpen,
canvasOpen,
}: PlaygroundButtonProps) => {
return hasIO ? (
<IOModal
open={open}

View file

@ -2,6 +2,7 @@ import useFlowStore from "@/stores/flowStore";
import { FlowPoolType } from "@/types/zustand/flow";
import { keepPreviousData } from "@tanstack/react-query";
import { AxiosResponse } from "axios";
import { useParams } from "react-router-dom";
import { useQueryFunctionType } from "../../../../types/api";
import { api } from "../../api";
import { getURL } from "../../helpers/constants";
@ -16,13 +17,17 @@ export const useGetBuildsQuery: useQueryFunctionType<
AxiosResponse<{ vertex_builds: FlowPoolType }>
> = (params) => {
const { query } = UseRequestProcessor();
const { id: routeFlowId } = useParams();
const setFlowPool = useFlowStore((state) => state.setFlowPool);
const currentFlow = useFlowStore((state) => state.currentFlow);
const responseFn = async () => {
const config = {};
config["params"] = { flow_id: params.flowId };
config["params"] = {
flow_id:
!params.flowId || params.flowId === "" ? routeFlowId : params.flowId,
};
const response = await api.get<any>(`${getURL("BUILDS")}`, config);

View file

@ -1,5 +1,5 @@
const SvgAnthropicBox = (props) => {
return props.isDark ? (
const SvgAnthropicBox = ({ isDark, ...props }) => {
return isDark ? (
<svg
width="38"
height="38"

View file

@ -57,7 +57,10 @@ export const GradientGroup = (props) => {
);
};
export const GradientUngroup = (props) => {
export const GradientUngroup = forwardRef<
SVGSVGElement,
React.PropsWithChildren<{}>
>((props, ref) => {
return (
<>
<svg width="0" height="0" style={{ position: "absolute" }}>
@ -68,7 +71,12 @@ export const GradientUngroup = (props) => {
</linearGradient>
</defs>
</svg>
<ForwardedIconComponent name="Ungroup" stroke="url(#grad4)" {...props} />
<ForwardedIconComponent
name="Ungroup"
stroke="url(#grad4)"
ref={ref}
{...props}
/>
</>
);
};
});

View file

@ -1,5 +1,5 @@
import React, { forwardRef } from "react";
import PerplexitySVG from "./perplexity";
import PerplexitySVG from "./Perplexity";
export const PerplexityIcon = forwardRef<
SVGSVGElement,

View file

@ -0,0 +1,228 @@
import { AgentQLIcon } from "@/icons/AgentQL";
import { AIMLIcon } from "@/icons/AIML";
import { AirbyteIcon } from "@/icons/Airbyte";
import { AnthropicIcon } from "@/icons/Anthropic";
import { ApifyIcon, ApifyWhiteIcon } from "@/icons/Apify";
import { ArizeIcon } from "@/icons/Arize";
import { ArXivIcon } from "@/icons/ArXiv";
import { AssemblyAIIcon } from "@/icons/AssemblyAI";
import { AstraDBIcon } from "@/icons/AstraDB";
import { AthenaIcon } from "@/icons/athena/index";
import { AWSIcon } from "@/icons/AWS";
import { AWSInvertedIcon } from "@/icons/AWSInverted";
import { AzureIcon } from "@/icons/Azure";
import { BingIcon } from "@/icons/Bing";
import { BotMessageSquareIcon } from "@/icons/BotMessageSquare";
import { BWPythonIcon } from "@/icons/BW python";
import { CassandraIcon } from "@/icons/Cassandra";
import { ChromaIcon } from "@/icons/ChromaIcon";
import { ClickhouseIcon } from "@/icons/Clickhouse";
import { CloudflareIcon } from "@/icons/Cloudflare";
import { CohereIcon } from "@/icons/Cohere";
import { ComposioIcon } from "@/icons/Composio";
import { ConfluenceIcon } from "@/icons/Confluence";
import { CouchbaseIcon } from "@/icons/Couchbase";
import { CrewAiIcon } from "@/icons/CrewAI";
import { DeepSeekIcon } from "@/icons/DeepSeek";
import { DropboxIcon } from "@/icons/Dropbox";
import { DuckDuckGoIcon } from "@/icons/DuckDuckGo";
import { ElasticsearchIcon } from "@/icons/ElasticsearchStore";
import { EvernoteIcon } from "@/icons/Evernote";
import { ExaIcon } from "@/icons/Exa";
import { FBIcon } from "@/icons/FacebookMessenger";
import { FirecrawlIcon } from "@/icons/Firecrawl";
import { freezeAllIcon } from "@/icons/freezeAll";
import { GitBookIcon } from "@/icons/GitBook";
import { GitLoaderIcon } from "@/icons/GitLoader";
import { GleanIcon } from "@/icons/Glean";
import { GlobeOkIcon } from "@/icons/globe-ok";
import { GmailIcon } from "@/icons/gmail";
import { GoogleIcon } from "@/icons/Google";
import { GoogleDriveIcon } from "@/icons/GoogleDrive";
import { GoogleGenerativeAIIcon } from "@/icons/GoogleGenerativeAI";
import {
GradientInfinity,
GradientSave,
GradientUngroup,
} from "@/icons/GradientSparkles";
import { GridHorizontalIcon } from "@/icons/GridHorizontal";
import { GroqIcon } from "@/icons/Groq";
import { HackerNewsIcon } from "@/icons/hackerNews";
import { HCDIcon } from "@/icons/HCD";
import { HomeAssistantIcon } from "@/icons/HomeAssistant";
import { HuggingFaceIcon } from "@/icons/HuggingFace";
import { WatsonxAiIcon } from "@/icons/IBMWatsonx";
import { IcosaIcon } from "@/icons/Icosa";
import { IFixIcon } from "@/icons/IFixIt";
import { JSIcon } from "@/icons/JSicon";
import { LangChainIcon } from "@/icons/LangChain";
import { LangwatchIcon } from "@/icons/Langwatch";
import { LMStudioIcon } from "@/icons/LMStudio";
import { MaritalkIcon } from "@/icons/Maritalk";
import { Mem0 } from "@/icons/Mem0";
import { MetaIcon } from "@/icons/Meta";
import { MidjourneyIcon } from "@/icons/Midjorney";
import { MilvusIcon } from "@/icons/Milvus";
import { MistralIcon } from "@/icons/mistral";
import { MongoDBIcon } from "@/icons/MongoDB";
import { NeedleIcon } from "@/icons/Needle";
import { NotDiamondIcon } from "@/icons/NotDiamond";
import { NotionIcon } from "@/icons/Notion";
import { NovitaIcon } from "@/icons/Novita";
import { NvidiaIcon } from "@/icons/Nvidia";
import { OlivyaIcon } from "@/icons/Olivya";
import { OllamaIcon } from "@/icons/Ollama";
import { OneDriveIcon } from "@/icons/OneDrive";
import { OpenAiIcon } from "@/icons/OpenAi";
import { OpenRouterIcon } from "@/icons/OpenRouter";
import { OpenSearch } from "@/icons/OpenSearch";
import { PerplexityIcon } from "@/icons/Perplexity";
import { PineconeIcon } from "@/icons/Pinecone";
import { PostgresIcon } from "@/icons/Postgres";
import { PythonIcon } from "@/icons/Python";
import { QDrantIcon } from "@/icons/QDrant";
import { QianFanChatIcon } from "@/icons/QianFanChat";
import { RedisIcon } from "@/icons/Redis";
import { SambaNovaIcon } from "@/icons/SambaNova";
import { ScrapeGraph } from "@/icons/ScrapeGraphAI";
import { SearchAPIIcon } from "@/icons/SearchAPI";
import { SearchHybridIcon } from "@/icons/SearchHybrid";
import { SearchLexicalIcon } from "@/icons/SearchLexical";
import { SearchVectorIcon } from "@/icons/SearchVector";
import { SearxIcon } from "@/icons/Searx";
import { SerperIcon } from "@/icons/Serper";
import { SerpSearchIcon } from "@/icons/SerpSearch";
import { ShareIcon } from "@/icons/Share";
import { Share2Icon } from "@/icons/Share2";
import { SlackIcon } from "@/icons/Slack";
import { SpiderIcon } from "@/icons/Spider";
import { Streamlit } from "@/icons/Streamlit";
import { SupabaseIcon } from "@/icons/supabase";
import { TavilyIcon } from "@/icons/Tavily";
import { ThumbDownIconCustom, ThumbUpIconCustom } from "@/icons/thumbs";
import { UnstructuredIcon } from "@/icons/Unstructured";
import { UpstashSvgIcon } from "@/icons/Upstash";
import { VectaraIcon } from "@/icons/VectaraIcon";
import { VertexAIIcon } from "@/icons/VertexAI";
import { WeaviateIcon } from "@/icons/Weaviate";
import { WikipediaIcon } from "@/icons/Wikipedia";
import { WolframIcon } from "@/icons/Wolfram";
import { XAIIcon } from "@/icons/xAI";
import { YouTubeSvgIcon as YouTubeIcon } from "@/icons/Youtube";
import { ZepMemoryIcon } from "@/icons/ZepMemory";
// Export the eagerly loaded icons map
export const eagerIconsMapping = {
"AI/ML": AIMLIcon,
AgentQL: AgentQLIcon,
Airbyte: AirbyteIcon,
Anthropic: AnthropicIcon,
Apify: ApifyIcon,
ApifyWhite: ApifyWhiteIcon,
ArXiv: ArXivIcon,
Arize: ArizeIcon,
AssemblyAI: AssemblyAIIcon,
AstraDB: AstraDBIcon,
Athena: AthenaIcon,
AWS: AWSIcon,
AWSInverted: AWSInvertedIcon,
Azure: AzureIcon,
Bing: BingIcon,
BotMessageSquare: BotMessageSquareIcon,
BWPython: BWPythonIcon,
Cassandra: CassandraIcon,
Chroma: ChromaIcon,
Clickhouse: ClickhouseIcon,
Cloudflare: CloudflareIcon,
Cohere: CohereIcon,
Composio: ComposioIcon,
Confluence: ConfluenceIcon,
Couchbase: CouchbaseIcon,
CrewAI: CrewAiIcon,
DeepSeek: DeepSeekIcon,
Dropbox: DropboxIcon,
DuckDuckGo: DuckDuckGoIcon,
ElasticsearchStore: ElasticsearchIcon,
Evernote: EvernoteIcon,
Exa: ExaIcon,
FacebookMessenger: FBIcon,
Firecrawl: FirecrawlIcon,
FreezeAll: freezeAllIcon,
GitBook: GitBookIcon,
GitLoader: GitLoaderIcon,
Glean: GleanIcon,
GlobeOk: GlobeOkIcon,
Google: GoogleIcon,
GoogleDrive: GoogleDriveIcon,
GoogleGenerativeAI: GoogleGenerativeAIIcon,
Gmail: GmailIcon,
GradientInfinity: GradientInfinity,
GradientSave: GradientSave,
GradientUngroup: GradientUngroup,
GridHorizontal: GridHorizontalIcon,
Groq: GroqIcon,
HackerNews: HackerNewsIcon,
HCD: HCDIcon,
HomeAssistant: HomeAssistantIcon,
HuggingFace: HuggingFaceIcon,
Icosa: IcosaIcon,
IFixIt: IFixIcon,
javascript: JSIcon,
LangChain: LangChainIcon,
Langwatch: LangwatchIcon,
LMStudio: LMStudioIcon,
Maritalk: MaritalkIcon,
Mem0: Mem0,
Meta: MetaIcon,
Midjourney: MidjourneyIcon,
Milvus: MilvusIcon,
Mistral: MistralIcon,
MongoDB: MongoDBIcon,
Needle: NeedleIcon,
NotDiamond: NotDiamondIcon,
Notion: NotionIcon,
Novita: NovitaIcon,
NVIDIA: NvidiaIcon,
Olivya: OlivyaIcon,
Ollama: OllamaIcon,
OneDrive: OneDriveIcon,
OpenAI: OpenAiIcon,
OpenRouter: OpenRouterIcon,
OpenSearch: OpenSearch,
Perplexity: PerplexityIcon,
Pinecone: PineconeIcon,
Postgres: PostgresIcon,
Python: PythonIcon,
QDrant: QDrantIcon,
QianFanChat: QianFanChatIcon,
Redis: RedisIcon,
SambaNova: SambaNovaIcon,
ScrapeGraph: ScrapeGraph,
SearchAPI: SearchAPIIcon,
SearchLexical: SearchLexicalIcon,
SearchHybrid: SearchHybridIcon,
SearchVector: SearchVectorIcon,
Searx: SearxIcon,
SerpSearch: SerpSearchIcon,
Serper: SerperIcon,
Share: ShareIcon,
Share2: Share2Icon,
Slack: SlackIcon,
Spider: SpiderIcon,
Streamlit: Streamlit,
Supabase: SupabaseIcon,
Tavily: TavilyIcon,
ThumbDownCustom: ThumbDownIconCustom,
ThumbUpCustom: ThumbUpIconCustom,
Unstructured: UnstructuredIcon,
Upstash: UpstashSvgIcon,
Vectara: VectaraIcon,
VertexAI: VertexAIIcon,
WatsonxAI: WatsonxAiIcon,
Weaviate: WeaviateIcon,
Wikipedia: WikipediaIcon,
Wolfram: WolframIcon,
xAI: XAIIcon,
YouTube: YouTubeIcon,
ZepMemory: ZepMemoryIcon,
};

View file

@ -0,0 +1,271 @@
// Export the lazy loading mapping for icons
export const lazyIconsMapping = {
"AI/ML": () =>
import("@/icons/AIML").then((mod) => ({ default: mod.AIMLIcon })),
AgentQL: () =>
import("@/icons/AgentQL").then((mod) => ({ default: mod.AgentQLIcon })),
Airbyte: () =>
import("@/icons/Airbyte").then((mod) => ({ default: mod.AirbyteIcon })),
Anthropic: () =>
import("@/icons/Anthropic").then((mod) => ({ default: mod.AnthropicIcon })),
Apify: () =>
import("@/icons/Apify").then((mod) => ({ default: mod.ApifyIcon })),
ApifyWhite: () =>
import("@/icons/Apify").then((mod) => ({ default: mod.ApifyWhiteIcon })),
ArXiv: () =>
import("@/icons/ArXiv").then((mod) => ({ default: mod.ArXivIcon })),
Arize: () =>
import("@/icons/Arize").then((mod) => ({ default: mod.ArizeIcon })),
AssemblyAI: () =>
import("@/icons/AssemblyAI").then((mod) => ({
default: mod.AssemblyAIIcon,
})),
AstraDB: () =>
import("@/icons/AstraDB").then((mod) => ({ default: mod.AstraDBIcon })),
Athena: () =>
import("@/icons/athena").then((mod) => ({ default: mod.AthenaIcon })),
AWS: () => import("@/icons/AWS").then((mod) => ({ default: mod.AWSIcon })),
Azure: () =>
import("@/icons/Azure").then((mod) => ({ default: mod.AzureIcon })),
Bing: () => import("@/icons/Bing").then((mod) => ({ default: mod.BingIcon })),
BWPython: () =>
import("@/icons/BW python").then((mod) => ({ default: mod.BWPythonIcon })),
Cassandra: () =>
import("@/icons/Cassandra").then((mod) => ({ default: mod.CassandraIcon })),
Chroma: () =>
import("@/icons/ChromaIcon").then((mod) => ({ default: mod.ChromaIcon })),
Clickhouse: () =>
import("@/icons/Clickhouse").then((mod) => ({
default: mod.ClickhouseIcon,
})),
Cloudflare: () =>
import("@/icons/Cloudflare").then((mod) => ({
default: mod.CloudflareIcon,
})),
Cohere: () =>
import("@/icons/Cohere").then((mod) => ({ default: mod.CohereIcon })),
Composio: () =>
import("@/icons/Composio").then((mod) => ({ default: mod.ComposioIcon })),
Confluence: () =>
import("@/icons/Confluence").then((mod) => ({
default: mod.ConfluenceIcon,
})),
Couchbase: () =>
import("@/icons/Couchbase").then((mod) => ({ default: mod.CouchbaseIcon })),
CrewAI: () =>
import("@/icons/CrewAI").then((mod) => ({ default: mod.CrewAiIcon })),
DeepSeek: () =>
import("@/icons/DeepSeek").then((mod) => ({ default: mod.DeepSeekIcon })),
Dropbox: () =>
import("@/icons/Dropbox").then((mod) => ({ default: mod.DropboxIcon })),
DuckDuckGo: () =>
import("@/icons/DuckDuckGo").then((mod) => ({
default: mod.DuckDuckGoIcon,
})),
ElasticsearchStore: () =>
import("@/icons/ElasticsearchStore").then((mod) => ({
default: mod.ElasticsearchIcon,
})),
Evernote: () =>
import("@/icons/Evernote").then((mod) => ({ default: mod.EvernoteIcon })),
Exa: () => import("@/icons/Exa").then((mod) => ({ default: mod.ExaIcon })),
FacebookMessenger: () =>
import("@/icons/FacebookMessenger").then((mod) => ({
default: mod.FBIcon,
})),
Firecrawl: () =>
import("@/icons/Firecrawl").then((mod) => ({ default: mod.FirecrawlIcon })),
FreezeAll: () =>
import("@/icons/freezeAll").then((mod) => ({ default: mod.freezeAllIcon })),
GitBook: () =>
import("@/icons/GitBook").then((mod) => ({ default: mod.GitBookIcon })),
GitLoader: () =>
import("@/icons/GitLoader").then((mod) => ({ default: mod.GitLoaderIcon })),
Glean: () =>
import("@/icons/Glean").then((mod) => ({ default: mod.GleanIcon })),
GlobeOk: () =>
import("@/icons/globe-ok").then((mod) => ({ default: mod.GlobeOkIcon })),
Google: () =>
import("@/icons/Google").then((mod) => ({ default: mod.GoogleIcon })),
GoogleDrive: () =>
import("@/icons/GoogleDrive").then((mod) => ({
default: mod.GoogleDriveIcon,
})),
GoogleGenerativeAI: () =>
import("@/icons/GoogleGenerativeAI").then((mod) => ({
default: mod.GoogleGenerativeAIIcon,
})),
Gmail: () =>
import("@/icons/gmail").then((mod) => ({ default: mod.GmailIcon })),
GradientInfinity: () =>
import("@/icons/GradientSparkles").then((mod) => ({
default: mod.GradientInfinity,
})),
GradientUngroup: () =>
import("@/icons/GradientSparkles").then((mod) => ({
default: mod.GradientUngroup,
})),
GridHorizontal: () =>
import("@/icons/GridHorizontal").then((mod) => ({
default: mod.GridHorizontalIcon,
})),
Groq: () => import("@/icons/Groq").then((mod) => ({ default: mod.GroqIcon })),
HackerNews: () =>
import("@/icons/hackerNews").then((mod) => ({
default: mod.HackerNewsIcon,
})),
HCD: () => import("@/icons/HCD").then((mod) => ({ default: mod.HCDIcon })),
HomeAssistant: () =>
import("@/icons/HomeAssistant").then((mod) => ({
default: mod.HomeAssistantIcon,
})),
HuggingFace: () =>
import("@/icons/HuggingFace").then((mod) => ({
default: mod.HuggingFaceIcon,
})),
Icosa: () =>
import("@/icons/Icosa").then((mod) => ({ default: mod.IcosaIcon })),
IFixIt: () =>
import("@/icons/IFixIt").then((mod) => ({ default: mod.IFixIcon })),
javascript: () =>
import("@/icons/JSicon").then((mod) => ({ default: mod.JSIcon })),
LangChain: () =>
import("@/icons/LangChain").then((mod) => ({ default: mod.LangChainIcon })),
Langwatch: () =>
import("@/icons/Langwatch").then((mod) => ({ default: mod.LangwatchIcon })),
LMStudio: () =>
import("@/icons/LMStudio").then((mod) => ({ default: mod.LMStudioIcon })),
Maritalk: () =>
import("@/icons/Maritalk").then((mod) => ({ default: mod.MaritalkIcon })),
Mem0: () => import("@/icons/Mem0").then((mod) => ({ default: mod.Mem0 })),
Meta: () => import("@/icons/Meta").then((mod) => ({ default: mod.MetaIcon })),
Midjourney: () =>
import("@/icons/Midjorney").then((mod) => ({
default: mod.MidjourneyIcon,
})),
Milvus: () =>
import("@/icons/Milvus").then((mod) => ({ default: mod.MilvusIcon })),
Mistral: () =>
import("@/icons/mistral").then((mod) => ({ default: mod.MistralIcon })),
MongoDB: () =>
import("@/icons/MongoDB").then((mod) => ({ default: mod.MongoDBIcon })),
Needle: () =>
import("@/icons/Needle").then((mod) => ({ default: mod.NeedleIcon })),
NotDiamond: () =>
import("@/icons/NotDiamond").then((mod) => ({
default: mod.NotDiamondIcon,
})),
Notion: () =>
import("@/icons/Notion").then((mod) => ({ default: mod.NotionIcon })),
Novita: () =>
import("@/icons/Novita").then((mod) => ({ default: mod.NovitaIcon })),
NVIDIA: () =>
import("@/icons/Nvidia").then((mod) => ({ default: mod.NvidiaIcon })),
Olivya: () =>
import("@/icons/Olivya").then((mod) => ({ default: mod.OlivyaIcon })),
Ollama: () =>
import("@/icons/Ollama").then((mod) => ({ default: mod.OllamaIcon })),
OpenAI: () =>
import("@/icons/OpenAi").then((mod) => ({ default: mod.OpenAiIcon })),
OpenRouter: () =>
import("@/icons/OpenRouter").then((mod) => ({
default: mod.OpenRouterIcon,
})),
OpenSearch: () =>
import("@/icons/OpenSearch").then((mod) => ({ default: mod.OpenSearch })),
Perplexity: () =>
import("@/icons/Perplexity").then((mod) => ({
default: mod.PerplexityIcon,
})),
Pinecone: () =>
import("@/icons/Pinecone").then((mod) => ({ default: mod.PineconeIcon })),
Postgres: () =>
import("@/icons/Postgres").then((mod) => ({ default: mod.PostgresIcon })),
Python: () =>
import("@/icons/Python").then((mod) => ({ default: mod.PythonIcon })),
QDrant: () =>
import("@/icons/QDrant").then((mod) => ({ default: mod.QDrantIcon })),
QianFanChat: () =>
import("@/icons/QianFanChat").then((mod) => ({
default: mod.QianFanChatIcon,
})),
Redis: () =>
import("@/icons/Redis").then((mod) => ({ default: mod.RedisIcon })),
SambaNova: () =>
import("@/icons/SambaNova").then((mod) => ({ default: mod.SambaNovaIcon })),
ScrapeGraph: () =>
import("@/icons/ScrapeGraphAI").then((mod) => ({
default: mod.ScrapeGraph,
})),
SearchAPI: () =>
import("@/icons/SearchAPI").then((mod) => ({ default: mod.SearchAPIIcon })),
SearchLexical: () =>
import("@/icons/SearchLexical").then((mod) => ({
default: mod.SearchLexicalIcon,
})),
SearchHybrid: () =>
import("@/icons/SearchHybrid").then((mod) => ({
default: mod.SearchHybridIcon,
})),
SearchVector: () =>
import("@/icons/SearchVector").then((mod) => ({
default: mod.SearchVectorIcon,
})),
Searx: () =>
import("@/icons/Searx").then((mod) => ({ default: mod.SearxIcon })),
SerpSearch: () =>
import("@/icons/SerpSearch").then((mod) => ({
default: mod.SerpSearchIcon,
})),
Serper: () =>
import("@/icons/Serper").then((mod) => ({ default: mod.SerperIcon })),
Share: () =>
import("@/icons/Share").then((mod) => ({ default: mod.ShareIcon })),
Share2: () =>
import("@/icons/Share2").then((mod) => ({ default: mod.Share2Icon })),
Slack: () =>
import("@/icons/Slack/SlackIcon").then((mod) => ({ default: mod.default })),
Spider: () =>
import("@/icons/Spider").then((mod) => ({ default: mod.SpiderIcon })),
Streamlit: () =>
import("@/icons/Streamlit").then((mod) => ({ default: mod.Streamlit })),
Supabase: () =>
import("@/icons/supabase").then((mod) => ({ default: mod.SupabaseIcon })),
Tavily: () =>
import("@/icons/Tavily").then((mod) => ({ default: mod.TavilyIcon })),
ThumbDownCustom: () =>
import("@/icons/thumbs").then((mod) => ({
default: mod.ThumbDownIconCustom,
})),
ThumbUpCustom: () =>
import("@/icons/thumbs").then((mod) => ({
default: mod.ThumbUpIconCustom,
})),
Unstructured: () =>
import("@/icons/Unstructured").then((mod) => ({
default: mod.UnstructuredIcon,
})),
Upstash: () =>
import("@/icons/Upstash").then((mod) => ({ default: mod.UpstashSvgIcon })),
Vectara: () =>
import("@/icons/VectaraIcon").then((mod) => ({ default: mod.VectaraIcon })),
VertexAI: () =>
import("@/icons/VertexAI").then((mod) => ({ default: mod.VertexAIIcon })),
WatsonxAI: () =>
import("@/icons/IBMWatsonx").then((mod) => ({
default: mod.WatsonxAiIcon,
})),
Weaviate: () =>
import("@/icons/Weaviate").then((mod) => ({ default: mod.WeaviateIcon })),
Wikipedia: () =>
import("@/icons/Wikipedia/Wikipedia").then((mod) => ({
default: mod.default,
})),
Wolfram: () =>
import("@/icons/Wolfram/Wolfram").then((mod) => ({ default: mod.default })),
xAI: () => import("@/icons/xAI").then((mod) => ({ default: mod.XAIIcon })),
YouTube: () =>
import("@/icons/Youtube").then((mod) => ({ default: mod.YouTubeSvgIcon })),
ZepMemory: () =>
import("@/icons/ZepMemory").then((mod) => ({ default: mod.ZepMemoryIcon })),
};

View file

@ -0,0 +1,467 @@
import {
AlertCircle,
AlertTriangle,
ArrowBigUp,
ArrowLeft,
ArrowRight,
ArrowRightLeft,
ArrowUpRight,
ArrowUpToLine,
AudioLines,
Bell,
Binary,
Blocks,
BookMarked,
BookOpenText,
BookmarkPlus,
Bot,
BotMessageSquare,
Boxes,
Braces,
BrainCircuit,
ChartNetwork,
Check,
CheckCheck,
CheckCircle2,
ChevronDown,
ChevronLeft,
ChevronRight,
ChevronRightSquare,
ChevronUp,
ChevronsDownUp,
ChevronsLeft,
ChevronsRight,
ChevronsUpDown,
ChevronsUpDownIcon,
Circle,
CircleCheckBig,
CircleDot,
CircleOff,
Clipboard,
CloudDownload,
Code,
Code2,
CodeXml,
Cog,
Columns2,
Combine,
Command,
Compass,
Copy,
CopyPlus,
CornerDownLeft,
Cpu,
Database,
DatabaseZap,
Delete,
DollarSign,
Dot,
Download,
DownloadCloud,
Edit,
Ellipsis,
EllipsisVertical,
Eraser,
ExternalLink,
Eye,
EyeOff,
File,
FileChartColumn,
FileClock,
FileCode2,
FileDown,
FileJson,
FilePen,
FileQuestion,
FileSearch,
FileSearch2,
FileSliders,
FileText,
FileType,
FileType2,
FileUp,
Filter,
FlaskConical,
FolderIcon,
FolderPlus,
FolderPlusIcon,
FolderSync,
FolderUp,
FormInput,
Forward,
Gift,
GitBranchPlus,
GitFork,
GithubIcon,
Globe,
GripVertical,
Group,
Hammer,
Heart,
HelpCircle,
Home,
Image,
Infinity,
Info,
InstagramIcon,
Key,
Keyboard,
Laptop2,
Layers,
LayoutGrid,
LayoutPanelTop,
Link,
Link2,
List,
ListChecks,
ListFilter,
ListOrdered,
ListX,
Loader2,
Lock,
LockOpen,
LogIn,
LogOut,
LucideSend,
Maximize2,
Menu,
MessageCircle,
MessageSquare,
MessageSquareMore,
MessagesSquare,
Mic,
Mic2,
MicOff,
Minimize2,
Minus,
Monitor,
Moon,
MoonIcon,
MoreHorizontal,
Network,
Newspaper,
NotebookPen,
OctagonAlert,
OptionIcon,
Package2,
Palette,
PanelLeftClose,
PanelLeftOpen,
PanelRightClose,
PanelRightOpen,
Paperclip,
PaperclipIcon,
Pen,
Pencil,
PencilLine,
PencilRuler,
PieChart,
Pin,
Plane,
Play,
Plus,
PlusCircle,
PlusSquare,
PocketKnife,
Radio,
Redo,
RefreshCcw,
RefreshCcwDot,
Repeat,
Replace,
RotateCcw,
Save,
SaveAll,
Scan,
ScanEye,
Scissors,
ScreenShare,
Scroll,
ScrollText,
Search,
Settings,
Settings2,
Share,
Share2,
Shield,
Sigma,
Sliders,
SlidersHorizontal,
Snowflake,
Sparkles,
Square,
SquareArrowOutUpRight,
SquareCode,
SquarePen,
SquarePlay,
StickyNote,
Store,
Sun,
SunIcon,
Table,
Tags,
TerminalIcon,
TerminalSquare,
TextCursorInput,
TextSearch,
TextSearchIcon,
ThumbsDown,
ThumbsUp,
ToyBrick,
Trash2,
Type,
Undo,
Ungroup,
UnlinkIcon,
Unplug,
Upload,
User,
UserCog2,
UserMinus2,
UserPlus2,
Users,
Users2,
Variable,
Wand2,
Workflow,
Wrench,
X,
XCircle,
Zap,
ZoomIn,
ZoomOut,
} from "lucide-react";
// Create a map of eagerly loaded Lucide icons
export const lucideIcons = {
AlertCircle,
AlertTriangle,
ArrowBigUp,
ArrowLeft,
ArrowRight,
ArrowRightLeft,
ArrowUpRight,
ArrowUpToLine,
AudioLines,
Bell,
Binary,
Blocks,
BookMarked,
BookOpenText,
BookmarkPlus,
Bot,
BotMessageSquare,
Boxes,
Braces,
BrainCircuit,
ChartNetwork,
Check,
CheckCheck,
CheckCircle2,
ChevronDown,
ChevronLeft,
ChevronRight,
ChevronRightSquare,
ChevronUp,
ChevronsDownUp,
ChevronsLeft,
ChevronsRight,
ChevronsUpDown,
ChevronsUpDownIcon,
Circle,
CircleCheckBig,
CircleDot,
CircleOff,
Clipboard,
CloudDownload,
Code,
Code2,
CodeXml,
Cog,
Columns2,
Combine,
Command,
Compass,
Copy,
CopyPlus,
CornerDownLeft,
Cpu,
Database,
DatabaseZap,
Delete,
DollarSign,
Dot,
Download,
DownloadCloud,
Edit,
Ellipsis,
EllipsisVertical,
Eraser,
ExternalLink,
Eye,
EyeOff,
File,
FileChartColumn,
FileClock,
FileCode2,
FileDown,
FileJson,
FilePen,
FileQuestion,
FileSearch,
FileSearch2,
FileSliders,
FileText,
FileType,
FileType2,
FileUp,
Filter,
FlaskConical,
FolderIcon,
FolderPlus,
FolderPlusIcon,
FolderSync,
FolderUp,
FormInput,
Forward,
Gift,
GitBranchPlus,
GitFork,
GithubIcon,
Globe,
GripVertical,
Group,
Hammer,
Heart,
HelpCircle,
Home,
Image,
Infinity,
Info,
Key,
Keyboard,
Laptop2,
Layers,
LayoutGrid,
LayoutPanelTop,
Link,
Link2,
List,
ListChecks,
ListFilter,
ListOrdered,
ListX,
Loader2,
Lock,
LockOpen,
LogIn,
LogOut,
LucideSend,
Maximize2,
Menu,
MessageCircle,
MessageSquare,
MessageSquareMore,
MessagesSquare,
Mic,
Mic2,
MicOff,
Minimize2,
Minus,
Monitor,
Moon,
MoonIcon,
MoreHorizontal,
Network,
Newspaper,
NotebookPen,
OctagonAlert,
OptionIcon,
Package2,
Palette,
PanelLeftClose,
PanelLeftOpen,
PanelRightClose,
PanelRightOpen,
Paperclip,
PaperclipIcon,
Pen,
Pencil,
PencilLine,
PencilRuler,
PieChart,
Pin,
Plane,
Play,
Plus,
PlusCircle,
PlusSquare,
PocketKnife,
Radio,
Redo,
RefreshCcw,
RefreshCcwDot,
Repeat,
Replace,
RotateCcw,
Save,
SaveAll,
Scan,
ScanEye,
Scissors,
ScreenShare,
Scroll,
ScrollText,
Search,
Settings,
Settings2,
Share,
Share2,
Shield,
Sigma,
Sliders,
SlidersHorizontal,
Snowflake,
Sparkles,
Square,
SquareArrowOutUpRight,
SquareCode,
SquarePen,
SquarePlay,
StickyNote,
Store,
Sun,
SunIcon,
Table,
Tags,
TerminalIcon,
TerminalSquare,
TextCursorInput,
TextSearch,
TextSearchIcon,
ThumbsDown,
ThumbsUp,
ToyBrick,
Trash2,
Type,
Undo,
Ungroup,
UnlinkIcon,
Unplug,
Upload,
User,
UserCog2,
UserMinus2,
UserPlus2,
Users,
Users2,
Variable,
Wand2,
Workflow,
Wrench,
X,
XCircle,
Zap,
ZoomIn,
ZoomOut,
};

View file

@ -1,3 +1,4 @@
import IconComponent from "@/components/common/genericIconComponent";
import * as Form from "@radix-ui/react-form";
import { Eye, EyeOff } from "lucide-react";
import { useContext, useEffect, useState } from "react";
@ -10,7 +11,6 @@ import {
UserManagementType,
inputHandlerEventType,
} from "../../types/components";
import { nodeIconsLucide } from "../../utils/styleUtils";
import BaseModal from "../baseModal";
export default function UserManagementModal({
@ -25,7 +25,6 @@ export default function UserManagementModal({
onConfirm,
asChild,
}: UserManagementType) {
const Icon: any = nodeIconsLucide[icon];
const [pwdVisible, setPwdVisible] = useState(false);
const [confirmPwdVisible, setConfirmPwdVisible] = useState(false);
const [open, setOpen] = useState(false);
@ -72,8 +71,8 @@ export default function UserManagementModal({
<BaseModal.Trigger asChild={asChild}>{children}</BaseModal.Trigger>
<BaseModal.Header description={titleHeader}>
<span className="pr-2">{title}</span>
<Icon
name="icon"
<IconComponent
name={icon}
className="h-6 w-6 pl-1 text-foreground"
aria-hidden="true"
/>

View file

@ -3,7 +3,7 @@ import IconComponent from "../../../../components/common/genericIconComponent";
import { DisclosureComponentType } from "../../../../types/components";
export default function DisclosureComponent({
button: { title, Icon, buttons = [] },
button: { title, icon, buttons = [] },
isChild = true,
children,
defaultOpen,
@ -23,13 +23,13 @@ export default function DisclosureComponent({
>
<div className={"flex gap-4" + (isChild ? " pl-2" : "")}>
{/* BUG ON THIS ICON */}
<Icon strokeWidth={1.5} size={22} className="text-primary" />
<IconComponent name={icon} />
<span className="components-disclosure-title">{title}</span>
</div>
<div className="components-disclosure-div">
{buttons.map((btn, index) => (
<button key={index} onClick={btn.onClick}>
{btn.Icon}
<IconComponent name={btn.icon} />
</button>
))}
<div>

View file

@ -3,7 +3,7 @@ import IconComponent from "../../../../components/common/genericIconComponent";
import { DisclosureComponentType } from "../../../../types/components";
export default function ParentDisclosureComponent({
button: { title, Icon, buttons = [], beta },
button: { title, icon, buttons = [], beta },
children,
defaultOpen,
testId,
@ -28,7 +28,7 @@ export default function ParentDisclosureComponent({
<div className="components-disclosure-div">
{buttons.map((btn, index) => (
<button key={index} onClick={btn.onClick}>
{btn.Icon}
<IconComponent name={btn.icon} />
</button>
))}
<div>

View file

@ -1,5 +1,5 @@
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { nodeColors, nodeIconsLucide, nodeNames } from "@/utils/styleUtils";
import { getNodeIcon, nodeColors } from "@/utils/styleUtils";
import { removeCountFromString } from "@/utils/utils";
import DisclosureComponent from "../../DisclosureComponent";
import SidebarDraggableComponent from "../sideBarDraggableComponent";
@ -19,8 +19,8 @@ export function SidebarCategoryComponent({
getFilterEdge.length !== 0 || search.length !== 0 ? true : false
}
button={{
title: nodeNames[name] ?? nodeNames.unknown,
Icon: nodeIconsLucide[name] ?? nodeIconsLucide.unknown,
title: name,
icon: name,
}}
>
<div className="side-bar-components-gap">

View file

@ -13,7 +13,6 @@ import useAlertStore from "../../../../stores/alertStore";
import useFlowStore from "../../../../stores/flowStore";
import { useTypesStore } from "../../../../stores/typesStore";
import { APIClassType, APIObjectType } from "../../../../types/api";
import { nodeIconsLucide } from "../../../../utils/styleUtils";
import ParentDisclosureComponent from "../ParentDisclosureComponent";
import { SidebarCategoryComponent } from "./SidebarCategoryComponent";
@ -253,7 +252,7 @@ export default function ExtraSidebar(): JSX.Element {
key={`${search.length !== 0}-${getFilterEdge.length !== 0}-Bundle`}
button={{
title: "Integrations",
Icon: nodeIconsLucide.unknown,
icon: "unknown",
}}
testId="bundle-extended-disclosure"
>
@ -281,7 +280,7 @@ export default function ExtraSidebar(): JSX.Element {
key={`${search.length !== 0}-${getFilterEdge.length !== 0}-Advanced`}
button={{
title: "Experimental",
Icon: nodeIconsLucide.unknown,
icon: "unknown",
beta: true,
}}
testId="extended-disclosure"

View file

@ -16,7 +16,7 @@ import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { FlowType } from "@/types/flow";
import { swatchColors } from "@/utils/styleUtils";
import { cn, getNumberFromString } from "@/utils/utils";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import useDescriptionModal from "../../hooks/use-description-modal";
import { useGetTemplateStyle } from "../../utils/get-template-style";
@ -40,6 +40,12 @@ const GridComponent = ({ flowData }: { flowData: FlowType }) => {
const { getIcon } = useGetTemplateStyle(flowData);
const [icon, setIcon] = useState<string>("");
useEffect(() => {
getIcon().then(setIcon);
}, [getIcon]);
const editFlowLink = `/flow/${flowData.id}${folderId ? `/folder/${folderId}` : ""}`;
const handleClick = async () => {
@ -91,7 +97,7 @@ const GridComponent = ({ flowData }: { flowData: FlowType }) => {
<div className="flex w-full items-center gap-4">
<div className={cn(`flex rounded-lg p-3`, swatchColors[swatchIndex])}>
<ForwardedIconComponent
name={getIcon()}
name={flowData?.icon || icon}
aria-hidden="true"
className="h-5 w-5"
/>

View file

@ -16,7 +16,7 @@ import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { FlowType } from "@/types/flow";
import { swatchColors } from "@/utils/styleUtils";
import { cn, getNumberFromString } from "@/utils/utils";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import useDescriptionModal from "../../hooks/use-description-modal";
import { useGetTemplateStyle } from "../../utils/get-template-style";
@ -75,6 +75,12 @@ const ListComponent = ({ flowData }: { flowData: FlowType }) => {
: getNumberFromString(flowData.gradient ?? flowData.id)) %
swatchColors.length;
const [icon, setIcon] = useState<string>("");
useEffect(() => {
getIcon().then(setIcon);
}, [getIcon]);
return (
<>
<Card
@ -99,7 +105,7 @@ const ListComponent = ({ flowData }: { flowData: FlowType }) => {
)}
>
<ForwardedIconComponent
name={flowData?.icon || getIcon()}
name={flowData?.icon || icon}
aria-hidden="true"
className="flex h-5 w-5 items-center justify-center"
/>

View file

@ -1,11 +1,11 @@
import { useTypesStore } from "@/stores/typesStore";
import { FlowType } from "@/types/flow";
import { nodeIconsLucide } from "@/utils/styleUtils";
import { iconExists } from "@/utils/styleUtils";
export const useGetTemplateStyle = (
flowData: FlowType,
): { getIcon: () => string } => {
const getIcon = () => {
): { getIcon: () => Promise<string> } => {
const getIcon = async () => {
if (
flowData.is_component &&
flowData.data?.nodes[0].type === "genericNode"
@ -14,7 +14,7 @@ export const useGetTemplateStyle = (
const isGroup = !!flowData.data?.nodes[0].data.node?.flow;
const icon = flowData.data?.nodes[0].data.node?.icon;
const types = useTypesStore((state) => state.types);
const name = nodeIconsLucide[dataType] ? dataType : types[dataType];
const name = (await iconExists(dataType)) ? dataType : types[dataType];
const iconName = icon || (isGroup ? "group_components" : name);
return iconName;
} else {

View file

@ -152,9 +152,9 @@ export type DisclosureComponentType = {
isChild?: boolean;
button: {
title: string;
Icon: React.ElementType;
icon: string;
buttons?: {
Icon: ReactElement;
icon: string;
title: string;
onClick: (event?: React.MouseEvent) => void;
}[];

File diff suppressed because it is too large Load diff