diff --git a/src/components/IconGrid/DetailsPanel.tsx b/src/components/IconGrid/DetailsPanel.tsx index 49f15bf..8d2c88a 100644 --- a/src/components/IconGrid/DetailsPanel.tsx +++ b/src/components/IconGrid/DetailsPanel.tsx @@ -15,7 +15,8 @@ import { } from "../../state/atoms"; import useTransientState from "../../hooks/useTransientState"; import TagCloud from "./TagCloud"; -import { IconEntry } from "../../lib"; +import { IconEntry, SnippetType } from "../../lib"; +import { getCodeSnippets, supportsWeight } from "../../utils"; const panelVariants = { open: { @@ -50,6 +51,13 @@ interface InfoPanelProps { entry: IconEntry; } +const renderedSnippets = [ + SnippetType.REACT, + SnippetType.VUE, + SnippetType.HTML, + SnippetType.FLUTTER, +]; + const DetailsPanel: React.FC = (props) => { const { index, spans, isDark, entry } = props; const { name, Icon, categories, tags } = entry; @@ -57,7 +65,10 @@ const DetailsPanel: React.FC = (props) => { const size = useRecoilValue(iconSizeAtom); const color = useRecoilValue(iconColorAtom); const setOpen = useSetRecoilState(iconPreviewOpenAtom); - const [copied, setCopied] = useTransientState(false, 2000); + const [copied, setCopied] = useTransientState( + false, + 2000 + ); const ref = useRef(null); useHotkeys("esc", () => setOpen(false)); @@ -75,38 +86,17 @@ const DetailsPanel: React.FC = (props) => { ? { color: disabledColor, userSelect: "none" } : { color: buttonColor }; - const snippets = { - html: - weight === "duotone" - ? "This weight is not yet supported" - : ``, - react: `<${Icon.displayName} size={${size}} ${ - color !== "#000000" ? `color="${color}" ` : "" - }${weight === "regular" ? "" : `weight="${weight}" `}/>`, - vue: ``, - flutter: - weight === "duotone" - ? "This weight is not yet supported" - : `Icon(\n PhosphorIcons.${ - Icon.displayName!.replace(/^\w/, (c) => c.toLowerCase()) - }${weight === "regular" - ? "" - : weight.replace(/^\w/, (c) => c.toUpperCase()) - },\n size: ${size.toFixed(1)},\n color: Color(0xff${ - color.replace("#", "") - }),\n)`, - }; + const snippets = getCodeSnippets({ + displayName: Icon.displayName!, + name, + weight, + size, + color, + }); const handleCopySnippet = ( event: React.MouseEvent, - type: "html" | "react" | "vue" | "flutter" + type: SnippetType ) => { event.currentTarget.blur(); setCopied(type); @@ -118,7 +108,7 @@ const DetailsPanel: React.FC = (props) => { event: React.MouseEvent ) => { event.currentTarget.blur(); - setCopied("svg"); + setCopied("SVG"); ref.current && void navigator.clipboard?.writeText(ref.current.outerHTML); }; @@ -171,6 +161,7 @@ const DetailsPanel: React.FC = (props) => { isDark={isDark} /> + = (props) => { variants={contentVariants} className="icon-usage" > -
- React -
-            {snippets.react}
-            
-          
-
-
- Vue -
-            {snippets.vue}
-            
-          
-
-
- HTML/CSS -
-            {snippets.html}
-            
-          
-
-
- Flutter -
-            {snippets.flutter}
-            
-          
-
+ {renderedSnippets.map((type) => { + const isWeightSupported = supportsWeight({ type, weight }); + + return ( +
+ {type} +
+                
+                  {isWeightSupported
+                    ? snippets[type]
+                    : "This weight is not yet supported"}
+                
+                
+              
+
+ ); + })}
diff --git a/src/lib/index.ts b/src/lib/index.ts index 352daf0..6c698a3 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -36,3 +36,10 @@ export interface IconEntry { tags: string[]; Icon: Icon; } + +export enum SnippetType { + REACT = "React", + VUE = "Vue", + HTML = "HTML/CSS", + FLUTTER = "Flutter", +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..8e56a5f --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,51 @@ +import { SnippetType, IconStyle } from "../lib"; + +export function getCodeSnippets({ + name, + displayName, + weight, + size, + color, +}: { + name: string; + displayName: string; + weight: IconStyle; + size: number; + color: string; +}): Record { + const isDefaultWeight = weight === "regular"; + const isDefaultColor = color === "#000000"; + + return { + [SnippetType.HTML]: ``, + [SnippetType.REACT]: `<${displayName} size={${size}} ${ + !isDefaultColor ? `color="${color}" ` : "" + }${isDefaultWeight ? "" : `weight="${weight}" `}/>`, + [SnippetType.VUE]: ``, + [SnippetType.FLUTTER]: `Icon(\n PhosphorIcons.${displayName.replace( + /^\w/, + (c) => c.toLowerCase() + )}${ + isDefaultWeight ? "" : weight.replace(/^\w/, (c) => c.toUpperCase()) + },\n size: ${size.toFixed(1)},\n${ + !isDefaultColor ? ` color: Color(0xff${color.replace("#", "")}),\n` : "" + })`, + }; +} + +export function supportsWeight({ + type, + weight, +}: { + type: SnippetType; + weight: IconStyle; +}): boolean { + if (type !== SnippetType.HTML && type !== SnippetType.FLUTTER) return true; + return weight !== IconStyle.DUOTONE; +}