Ctrl K
ComunidadGuías…

shared/utils/IconLibrary.tsx

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Import icons individually — the package barrel is also loaded as a whole pack
// by the Mermaid extension, so a shared import puts every icon in the bundle.
import { faAndroid } from "@fortawesome/free-brands-svg-icons/faAndroid";
import { faApple } from "@fortawesome/free-brands-svg-icons/faApple";
import { faBluesky } from "@fortawesome/free-brands-svg-icons/faBluesky";
import { faCodepen } from "@fortawesome/free-brands-svg-icons/faCodepen";
import { faDiscord } from "@fortawesome/free-brands-svg-icons/faDiscord";
import { faDocker } from "@fortawesome/free-brands-svg-icons/faDocker";
import { faDropbox } from "@fortawesome/free-brands-svg-icons/faDropbox";
import { faGithub } from "@fortawesome/free-brands-svg-icons/faGithub";
import { faGitlab } from "@fortawesome/free-brands-svg-icons/faGitlab";
import { faPaypal } from "@fortawesome/free-brands-svg-icons/faPaypal";
import { faPython } from "@fortawesome/free-brands-svg-icons/faPython";
import { faShopify } from "@fortawesome/free-brands-svg-icons/faShopify";
import { faSlack } from "@fortawesome/free-brands-svg-icons/faSlack";
import { faSquareJs } from "@fortawesome/free-brands-svg-icons/faSquareJs";
import { faSwift } from "@fortawesome/free-brands-svg-icons/faSwift";
import { faWebAwesome } from "@fortawesome/free-brands-svg-icons/faWebAwesome";
import { faWindows } from "@fortawesome/free-brands-svg-icons/faWindows";
import { faXTwitter } from "@fortawesome/free-brands-svg-icons/faXTwitter";
import { faBagShopping } from "@fortawesome/free-solid-svg-icons/faBagShopping";
import { faBook } from "@fortawesome/free-solid-svg-icons/faBook";
import { faBrush } from "@fortawesome/free-solid-svg-icons/faBrush";
import { faCake } from "@fortawesome/free-solid-svg-icons/faCake";
import { faCat } from "@fortawesome/free-solid-svg-icons/faCat";
import { faCircle } from "@fortawesome/free-solid-svg-icons/faCircle";
import { faClapperboard } from "@fortawesome/free-solid-svg-icons/faClapperboard";
import { faCompactDisc } from "@fortawesome/free-solid-svg-icons/faCompactDisc";
import { faCookieBite } from "@fortawesome/free-solid-svg-icons/faCookieBite";
import { faCrow } from "@fortawesome/free-solid-svg-icons/faCrow";
import { faCrown } from "@fortawesome/free-solid-svg-icons/faCrown";
import { faCube } from "@fortawesome/free-solid-svg-icons/faCube";
import { faDiamond } from "@fortawesome/free-solid-svg-icons/faDiamond";
import { faDisplay } from "@fortawesome/free-solid-svg-icons/faDisplay";
import { faDna } from "@fortawesome/free-solid-svg-icons/faDna";
import { faDog } from "@fortawesome/free-solid-svg-icons/faDog";
import { faDollarSign } from "@fortawesome/free-solid-svg-icons/faDollarSign";
import { faDroplet } from "@fortawesome/free-solid-svg-icons/faDroplet";
import { faFaceDizzy } from "@fortawesome/free-solid-svg-icons/faFaceDizzy";
import { faFaceGrinStars } from "@fortawesome/free-solid-svg-icons/faFaceGrinStars";
import { faFaceLaugh } from "@fortawesome/free-solid-svg-icons/faFaceLaugh";
import { faFaceMeh } from "@fortawesome/free-solid-svg-icons/faFaceMeh";
import { faFaceSmileBeam } from "@fortawesome/free-solid-svg-icons/faFaceSmileBeam";
import { faFaceSmileWink } from "@fortawesome/free-solid-svg-icons/faFaceSmileWink";
import { faFaceSurprise } from "@fortawesome/free-solid-svg-icons/faFaceSurprise";
import { faFeather } from "@fortawesome/free-solid-svg-icons/faFeather";
import { faFish } from "@fortawesome/free-solid-svg-icons/faFish";
import { faFlaskVial } from "@fortawesome/free-solid-svg-icons/faFlaskVial";
import { faFolderClosed } from "@fortawesome/free-solid-svg-icons/faFolderClosed";
import { faGamepad } from "@fortawesome/free-solid-svg-icons/faGamepad";
import { faGauge } from "@fortawesome/free-solid-svg-icons/faGauge";
import { faGem } from "@fortawesome/free-solid-svg-icons/faGem";
import { faGift } from "@fortawesome/free-solid-svg-icons/faGift";
import { faHammer } from "@fortawesome/free-solid-svg-icons/faHammer";
import { faHandsClapping } from "@fortawesome/free-solid-svg-icons/faHandsClapping";
import { faHeart } from "@fortawesome/free-solid-svg-icons/faHeart";
import { faHexagon } from "@fortawesome/free-solid-svg-icons/faHexagon";
import { faIndustry } from "@fortawesome/free-solid-svg-icons/faIndustry";
import { faKitMedical } from "@fortawesome/free-solid-svg-icons/faKitMedical";
import { faLaptop } from "@fortawesome/free-solid-svg-icons/faLaptop";
import { faLaptopCode } from "@fortawesome/free-solid-svg-icons/faLaptopCode";
import { faMagnet } from "@fortawesome/free-solid-svg-icons/faMagnet";
import { faMap } from "@fortawesome/free-solid-svg-icons/faMap";
import { faMicrochip } from "@fortawesome/free-solid-svg-icons/faMicrochip";
import { faMountainSun } from "@fortawesome/free-solid-svg-icons/faMountainSun";
import { faMugHot } from "@fortawesome/free-solid-svg-icons/faMugHot";
import { faNetworkWired } from "@fortawesome/free-solid-svg-icons/faNetworkWired";
import { faNewspaper } from "@fortawesome/free-solid-svg-icons/faNewspaper";
import { faPaintRoller } from "@fortawesome/free-solid-svg-icons/faPaintRoller";
import { faPassport } from "@fortawesome/free-solid-svg-icons/faPassport";
import { faPaw } from "@fortawesome/free-solid-svg-icons/faPaw";
import { faPenRuler } from "@fortawesome/free-solid-svg-icons/faPenRuler";
import { faPentagon } from "@fortawesome/free-solid-svg-icons/faPentagon";
import { faPesoSign } from "@fortawesome/free-solid-svg-icons/faPesoSign";
import { faPhoneVolume } from "@fortawesome/free-solid-svg-icons/faPhoneVolume";
import { faPizzaSlice } from "@fortawesome/free-solid-svg-icons/faPizzaSlice";
import { faPrescription } from "@fortawesome/free-solid-svg-icons/faPrescription";
import { faPuzzlePiece } from "@fortawesome/free-solid-svg-icons/faPuzzlePiece";
import { faRainbow } from "@fortawesome/free-solid-svg-icons/faRainbow";
import { faRecordVinyl } from "@fortawesome/free-solid-svg-icons/faRecordVinyl";
import { faRoad } from "@fortawesome/free-solid-svg-icons/faRoad";
import { faRobot } from "@fortawesome/free-solid-svg-icons/faRobot";
import { faRocket } from "@fortawesome/free-solid-svg-icons/faRocket";
import { faSailboat } from "@fortawesome/free-solid-svg-icons/faSailboat";
import { faScissors } from "@fortawesome/free-solid-svg-icons/faScissors";
import { faSeedling } from "@fortawesome/free-solid-svg-icons/faSeedling";
import { faShield } from "@fortawesome/free-solid-svg-icons/faShield";
import { faShirt } from "@fortawesome/free-solid-svg-icons/faShirt";
import { faShop } from "@fortawesome/free-solid-svg-icons/faShop";
import { faSnowflake } from "@fortawesome/free-solid-svg-icons/faSnowflake";
import { faSocks } from "@fortawesome/free-solid-svg-icons/faSocks";
import { faSolarPanel } from "@fortawesome/free-solid-svg-icons/faSolarPanel";
import { faSpa } from "@fortawesome/free-solid-svg-icons/faSpa";
import { faSpiral } from "@fortawesome/free-solid-svg-icons/faSpiral";
import { faSquare } from "@fortawesome/free-solid-svg-icons/faSquare";
import { faStarAndCrescent } from "@fortawesome/free-solid-svg-icons/faStarAndCrescent";
import { faStarOfLife } from "@fortawesome/free-solid-svg-icons/faStarOfLife";
import { faSterlingSign } from "@fortawesome/free-solid-svg-icons/faSterlingSign";
import { faSwatchbook } from "@fortawesome/free-solid-svg-icons/faSwatchbook";
import { faTent } from "@fortawesome/free-solid-svg-icons/faTent";
import { faTooth } from "@fortawesome/free-solid-svg-icons/faTooth";
import { faTowerCell } from "@fortawesome/free-solid-svg-icons/faTowerCell";
import { faTractor } from "@fortawesome/free-solid-svg-icons/faTractor";
import { faTrain } from "@fortawesome/free-solid-svg-icons/faTrain";
import { faTree } from "@fortawesome/free-solid-svg-icons/faTree";
import { faTrophy } from "@fortawesome/free-solid-svg-icons/faTrophy";
import { faUmbrella } from "@fortawesome/free-solid-svg-icons/faUmbrella";
import { faUmbrellaBeach } from "@fortawesome/free-solid-svg-icons/faUmbrellaBeach";
import { faUniversalAccess } from "@fortawesome/free-solid-svg-icons/faUniversalAccess";
import { faUserGraduate } from "@fortawesome/free-solid-svg-icons/faUserGraduate";
import { faUtensils } from "@fortawesome/free-solid-svg-icons/faUtensils";
import { faVault } from "@fortawesome/free-solid-svg-icons/faVault";
import { faWandSparkles } from "@fortawesome/free-solid-svg-icons/faWandSparkles";
import { faWheelchairMove } from "@fortawesome/free-solid-svg-icons/faWheelchairMove";
import { faWorm } from "@fortawesome/free-solid-svg-icons/faWorm";
import { faYenSign } from "@fortawesome/free-solid-svg-icons/faYenSign";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { intersection } from "es-toolkit/compat";
import {
  BookmarkedIcon,
  BicycleIcon,
  AcademicCapIcon,
  BeakerIcon,
  BuildingBlocksIcon,
  BrowserIcon,
  CollectionIcon,
  CoinsIcon,
  CameraIcon,
  CarrotIcon,
  FlameIcon,
  HashtagIcon,
  GraphIcon,
  InternetIcon,
  LibraryIcon,
  PlaneIcon,
  RamenIcon,
  CloudIcon,
  CodeIcon,
  EditIcon,
  EmailIcon,
  EyeIcon,
  GlobeIcon,
  InfoIcon,
  IceCreamIcon,
  ImageIcon,
  LeafIcon,
  LightBulbIcon,
  MathIcon,
  MoonIcon,
  NotepadIcon,
  TeamIcon,
  PadlockIcon,
  PaletteIcon,
  PromoteIcon,
  QuestionMarkIcon,
  SportIcon,
  SunIcon,
  ShapesIcon,
  TargetIcon,
  TerminalIcon,
  ToolsIcon,
  VehicleIcon,
  WarningIcon,
  DatabaseIcon,
  SmileyIcon,
  LightningIcon,
  ClockIcon,
  DoneIcon,
  FeedbackIcon,
  ServerRackIcon,
  ThumbsUpIcon,
  TruckIcon,
} from "outline-icons";
import * as React from "react";
import styled from "styled-components";
import LetterIcon from "../components/LetterIcon";

type IconMapping = {
  component: React.ComponentType<FAProps>;
  keywords?: string;
};

type FAProps = {
  color?: string;
  size?: number;
  className?: string;
  style?: React.CSSProperties;
  children?: React.ReactNode;
};

export class IconLibrary {
  /**
   * Get the component for a given icon name
   *
   * @param icon The name of the icon
   * @returns The component for the icon
   */
  public static getComponent(icon: string) {
    return this.mapping[icon].component;
  }

  /**
   * Find an icon by keyword. This is useful for searching for an icon based on a user's input.
   *
   * @param keyword The keyword to search for
   * @returns The name of the icon that matches the keyword, or undefined if no match is found
   */
  public static findIconByKeyword(keyword: string) {
    const keys = Object.keys(this.mapping);

    for (const key of keys) {
      const icon = this.mapping[key];
      const keywords = icon.keywords?.split(" ");
      const namewords = keyword.toLocaleLowerCase().split(" ");
      const matches = intersection(namewords, keywords);

      if (matches.length > 0) {
        return key;
      }
    }

    return undefined;
  }

  /**
   * Find icons.
   *
   * @param query The query to search for
   * @returns The icon results.
   */
  public static findIcons(query: string) {
    return Object.keys(this.mapping)
      .map((key) => {
        const icon = this.mapping[key];
        const keywords = `${icon.keywords ?? ""} ${key}`;

        if (keywords.includes(query.toLocaleLowerCase())) {
          return key;
        }
        return undefined;
      })
      .filter((icon: string | undefined): icon is string => !!icon);
  }

  /**
   * A map of all icons available to end users in the app. This does not include icons that are used
   * internally only, which can be imported from `outline-icons` directly.
   */
  public static mapping: Record<string, IconMapping> = {
    // Internal icons
    academicCap: {
      component: AcademicCapIcon,
      keywords: "learn teach lesson guide tutorial onboarding training",
    },
    bicycle: {
      component: BicycleIcon,
      keywords: "bicycle bike cycle",
    },
    beaker: {
      component: BeakerIcon,
      keywords: "lab research experiment test",
    },
    buildingBlocks: {
      component: BuildingBlocksIcon,
      keywords: "app blocks product prototype",
    },
    bookmark: {
      component: BookmarkedIcon,
      keywords: "bookmark",
    },
    browser: {
      component: BrowserIcon,
      keywords: "browser web app",
    },
    collection: {
      component: (props) => <CollectionIcon expanded {...props} />,
      keywords: "collection",
    },
    coins: {
      component: CoinsIcon,
      keywords: "coins money finance sales income revenue cash",
    },
    camera: {
      component: CameraIcon,
      keywords: "photo picture",
    },
    carrot: {
      component: CarrotIcon,
      keywords: "food vegetable produce",
    },
    clock: {
      component: ClockIcon,
      keywords: "time",
    },
    cloud: {
      component: CloudIcon,
      keywords: "cloud service aws infrastructure",
    },
    code: {
      component: CodeIcon,
      keywords: "developer api code development engineering programming",
    },
    database: {
      component: DatabaseIcon,
      keywords: "server ops database",
    },
    done: {
      component: DoneIcon,
      keywords: "checkmark success complete finished",
    },
    email: {
      component: EmailIcon,
      keywords: "email at",
    },
    eye: {
      component: EyeIcon,
      keywords: "eye view",
    },
    feedback: {
      component: FeedbackIcon,
      keywords: "faq help support",
    },
    flame: {
      component: FlameIcon,
      keywords: "fire flame hot",
    },
    graph: {
      component: GraphIcon,
      keywords: "chart analytics data",
    },
    globe: {
      component: GlobeIcon,
      keywords: "world translate",
    },
    hashtag: {
      component: HashtagIcon,
      keywords: "social media tag",
    },
    info: {
      component: InfoIcon,
      keywords: "info information",
    },
    icecream: {
      component: IceCreamIcon,
      keywords: "food dessert cone scoop",
    },
    image: {
      component: ImageIcon,
      keywords: "image photo picture",
    },
    internet: {
      component: InternetIcon,
      keywords: "network global globe world",
    },
    leaf: {
      component: LeafIcon,
      keywords: "leaf plant outdoors nature ecosystem climate",
    },
    library: {
      component: LibraryIcon,
      keywords: "library collection archive",
    },
    lightbulb: {
      component: LightBulbIcon,
      keywords: "lightbulb idea",
    },
    lightning: {
      component: LightningIcon,
      keywords: "lightning fast zap",
    },
    letter: {
      component: LetterIcon,
      keywords: "letter",
    },
    math: {
      component: MathIcon,
      keywords: "math formula",
    },
    moon: {
      component: MoonIcon,
      keywords: "night moon dark",
    },
    notepad: {
      component: NotepadIcon,
      keywords: "journal notepad write notes",
    },
    padlock: {
      component: PadlockIcon,
      keywords: "padlock private security authentication authorization auth",
    },
    palette: {
      component: PaletteIcon,
      keywords: "design palette art brand",
    },
    pencil: {
      component: EditIcon,
      keywords: "copy writing post blog",
    },
    plane: {
      component: PlaneIcon,
      keywords: "airplane travel flight trip vacation",
    },
    promote: {
      component: PromoteIcon,
      keywords: "marketing promotion",
    },
    ramen: {
      component: RamenIcon,
      keywords: "soup food noodle bowl meal",
    },
    question: {
      component: QuestionMarkIcon,
      keywords: "question help support faq",
    },
    server: {
      component: ServerRackIcon,
      keywords: "ops infra server",
    },
    sun: {
      component: SunIcon,
      keywords: "day sun weather",
    },
    shapes: {
      component: ShapesIcon,
      keywords: "blocks toy",
    },
    sport: {
      component: SportIcon,
      keywords: "sport outdoor racket game",
    },
    smiley: {
      component: SmileyIcon,
      keywords: "emoji smiley happy",
    },
    target: {
      component: TargetIcon,
      keywords: "target goal sales",
    },
    team: {
      component: TeamIcon,
      keywords: "team building organization office",
    },
    terminal: {
      component: TerminalIcon,
      keywords: "terminal code",
    },
    thumbsup: {
      component: ThumbsUpIcon,
      keywords: "like social favorite upvote",
    },
    truck: {
      component: TruckIcon,
      keywords: "truck transport vehicle",
    },
    tools: {
      component: ToolsIcon,
      keywords: "tool settings",
    },
    vehicle: {
      component: VehicleIcon,
      keywords: "truck car travel transport",
    },
    warning: {
      component: WarningIcon,
      keywords: "warning alert error",
    },

    // Font awesome
    ...Object.fromEntries(
      [
        faBagShopping,
        faBook,
        faBrush,
        faCake,
        faCat,
        faClapperboard,
        faCompactDisc,
        faCookieBite,
        faCrow,
        faCrown,
        faCube,
        faDna,
        faDog,
        faDollarSign,
        faDisplay,
        faDroplet,
        faFaceDizzy,
        faFaceGrinStars,
        faFaceLaugh,
        faFaceMeh,
        faFaceSmileBeam,
        faFaceSmileWink,
        faFaceSurprise,
        faFeather,
        faFish,
        faFolderClosed,
        faFlaskVial,
        faGamepad,
        faGauge,
        faGem,
        faGift,
        faHammer,
        faHandsClapping,
        faHeart,
        faIndustry,
        faKitMedical,
        faLaptop,
        faLaptopCode,
        faMagnet,
        faMap,
        faMicrochip,
        faMountainSun,
        faMugHot,
        faNetworkWired,
        faNewspaper,
        faPaintRoller,
        faPassport,
        faPaw,
        faPenRuler,
        faPesoSign,
        faPhoneVolume,
        faPizzaSlice,
        faPrescription,
        faPuzzlePiece,
        faRainbow,
        faRecordVinyl,
        faRoad,
        faRobot,
        faRocket,
        faSailboat,
        faScissors,
        faSeedling,
        faShield,
        faShirt,
        faShop,
        faSnowflake,
        faSocks,
        faSolarPanel,
        faSpa,
        faStarAndCrescent,
        faStarOfLife,
        faSterlingSign,
        faSwatchbook,
        faTent,
        faTooth,
        faTowerCell,
        faTractor,
        faTrain,
        faTree,
        faTrophy,
        faUmbrella,
        faUmbrellaBeach,
        faUniversalAccess,
        faUserGraduate,
        faUtensils,
        faVault,
        faWandSparkles,
        faWebAwesome,
        faWheelchairMove,
        faWorm,
        faYenSign,
        faApple,
        faWindows,
        faAndroid,
        faSquareJs,
        faPython,
        faXTwitter,
        faBluesky,
        faGithub,
        faGitlab,
        faDiscord,
        faDocker,
        faCodepen,
        faDropbox,
        faPaypal,
        faShopify,
        faSwift,
        faSlack,
        faCircle,
        faSquare,
        faPentagon,
        faHexagon,
        faDiamond,
        faSpiral,
      ].map((icon) => [
        icon.iconName,
        {
          component: ({ color, size = 24, className, style }: FAProps) => (
            <FontAwesomeWrapper size={size}>
              <FontAwesomeIcon
                style={{
                  width: 0.6666666667 * size,
                  height: 0.6666666667 * size,
                  ...style,
                }}
                color={color}
                icon={icon}
                className={className}
              />
            </FontAwesomeWrapper>
          ),
        },
      ])
    ),
  } as const;
}

const FontAwesomeWrapper = styled.span<{ size: number }>`
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: ${(props) => props.size}px;
  height: ${(props) => props.size}px;
`;