react-fa-picker
Version:
A reusable React Icon Picker component, bundled with its own Tailwind CSS build.
111 lines (101 loc) • 2.87 kB
text/typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import * as brands from "@fortawesome/free-brands-svg-icons";
import * as regular from "@fortawesome/free-regular-svg-icons";
import * as solid from "@fortawesome/free-solid-svg-icons";
import { IconCategory, IconType } from "./types";
// Track seen unicodes to filter duplicates globally
const seenUnicodes = new Set<string>();
/**
* Gets the icon class name
*/
export const getIconClassName = (iconDef: IconDefinition): string => {
if (!iconDef || !iconDef.iconName) return "";
return `fa-${iconDef.iconName}`;
};
/**
* Gets the icon unicode
*/
export const getIconUnicode = (icon: IconDefinition): string => {
if (!icon || !icon.icon) return "";
const unicodeHex =
Array.isArray(icon.icon) && icon.icon.length > 0
? (icon.icon[3] as string)
: "";
return unicodeHex ? `\\u${unicodeHex}` : "";
};
/**
* Extract icons from a FontAwesome package
*/
function extractIcons(
pkg: Record<string, any>,
categoryName: string,
prefixTag: string,
): IconType[] {
return Object.values(pkg)
.filter(
(def): def is IconDefinition & { iconName: string; prefix: string } =>
Boolean(def?.iconName),
)
.map((def) => {
const name = def.iconName;
const unicode = getIconUnicode(def);
return {
id: unicode || `${prefixTag}-${name}`, // fallback to name if unicode missing
name: `${prefixTag}-${name}`,
icon: def,
unicode,
class: getIconClassName(def),
category: categoryName,
};
})
.filter((icon) => {
if (!icon.unicode || seenUnicodes.has(icon.unicode)) return false;
seenUnicodes.add(icon.unicode);
return true;
});
}
/**
* Categorized icon list with prefix-tagged names
*/
const iconCategories: IconCategory[] = [
{ name: "Solid", icons: extractIcons(solid, "Solid", "solid") },
{ name: "Regular", icons: extractIcons(regular, "Regular", "regular") },
{ name: "Brands", icons: extractIcons(brands, "Brands", "brands") },
];
/**
* Get all icons as flat list
*/
export function getAllIcons(): IconType[] {
return iconCategories.flatMap((category) => category.icons);
}
/**
* Get icon categories
*/
export function getIconCategories(): IconCategory[] {
return iconCategories;
}
/**
* Generate random icon name
*/
export const generateRandomIconName = (prefix = "icon"): string => {
const randomId = Math.floor(Math.random() * 10000);
const suffixes = [
"home",
"user",
"settings",
"file",
"folder",
"chart",
"mail",
"calendar",
"map",
"image",
"video",
"audio",
"lock",
"key",
];
const randomSuffix = suffixes[Math.floor(Math.random() * suffixes.length)];
return `${prefix}-${randomSuffix}-${randomId}`;
};