返回 presentation-ai
presentation-icon.tsx
根目录 / src / components / notebook / presentation / editor / custom-elements / presentation-icon.tsx
1 "use client";
2
3 import { useEffect, useState } from "react";
4
5 import {
6 DEFAULT_PRESENTATION_ICON,
7 resolvePresentationIcon,
8 type ResolvedPresentationIcon,
9 } from "./presentation-icon-utils";
10
11 export function PresentationIcon({
12 icon,
13 size = 24,
14 className,
15 iconClassName,
16 fallbackIcon,
17 }: {
18 icon?: string;
19 size?: number;
20 className?: string;
21 iconClassName?: string;
22 fallbackIcon?: string;
23 }) {
24 const [resolvedIcon, setResolvedIcon] =
25 useState<ResolvedPresentationIcon | null>(null);
26
27 useEffect(() => {
28 let cancelled = false;
29
30 const run = async () => {
31 const normalizedIcon = icon?.trim();
32 const normalizedFallbackIcon = fallbackIcon?.trim();
33 const nextIconName = normalizedIcon || normalizedFallbackIcon;
34
35 if (!nextIconName) {
36 if (!cancelled) {
37 setResolvedIcon(null);
38 }
39 return;
40 }
41
42 let nextResolvedIcon: ResolvedPresentationIcon | null = null;
43
44 try {
45 nextResolvedIcon = await resolvePresentationIcon(nextIconName);
46 } catch (error) {
47 console.error("Error resolving presentation icon:", error);
48 }
49
50 let fallbackResolvedIcon: ResolvedPresentationIcon | null = null;
51
52 if (!nextResolvedIcon && normalizedIcon) {
53 try {
54 fallbackResolvedIcon = await resolvePresentationIcon(
55 normalizedFallbackIcon || DEFAULT_PRESENTATION_ICON,
56 );
57 } catch (error) {
58 console.error("Error resolving fallback presentation icon:", error);
59 }
60 }
61
62 if (!cancelled) {
63 setResolvedIcon(nextResolvedIcon ?? fallbackResolvedIcon);
64 }
65 };
66
67 void run();
68
69 return () => {
70 cancelled = true;
71 };
72 }, [fallbackIcon, icon]);
73
74 if (!resolvedIcon) return null;
75
76 const IconComponent = resolvedIcon.Component;
77
78 return (
79 <div className={className}>
80 <IconComponent aria-hidden="true" className={iconClassName} size={size} />
81 </div>
82 );
83 }
84
84 lines Plain Text