Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/components/icon.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45declare var DEBUG: boolean; // comes from static webpack; not defined in other contexts.67import React from "react";89import { CSS } from "@cocalc/frontend/app-framework";10import useOnFrontend from "./use-on-frontend";1112import {13AimOutlined,14AlignCenterOutlined,15AlignLeftOutlined,16AlignRightOutlined,17ApiOutlined,18AppstoreOutlined,19AreaChartOutlined,20ArrowDownOutlined,21ArrowLeftOutlined,22ArrowRightOutlined,23ArrowUpOutlined,24ArrowsAltOutlined,25AudioOutlined,26BackwardOutlined,27BankOutlined,28BellFilled,29BellOutlined,30BoldOutlined,31BookOutlined,32BorderOutlined,33BugOutlined,34BulbOutlined,35CalculatorOutlined,36CalendarOutlined,37CameraOutlined,38CaretDownFilled,39CaretLeftFilled,40CaretRightFilled,41CaretUpFilled,42CheckCircleOutlined,43CheckOutlined,44CheckSquareOutlined,45ClearOutlined,46ClockCircleOutlined,47CloseCircleFilled,48CloseCircleOutlined,49CloseCircleTwoTone,50CloseOutlined,51CloudDownloadOutlined,52CloudFilled,53CloudServerOutlined,54CloudUploadOutlined,55ClusterOutlined,56CodeOutlined,57CoffeeOutlined,58ColumnHeightOutlined,59ColumnWidthOutlined,60CommentOutlined,61CompassOutlined,62ControlOutlined,63CopyOutlined,64CreditCardOutlined,65DashboardOutlined,66DatabaseFilled,67DatabaseOutlined,68DeleteOutlined,69DeliveredProcedureOutlined,70DeploymentUnitOutlined,71DesktopOutlined,72DoubleLeftOutlined,73DoubleRightOutlined,74DownCircleOutlined,75DownOutlined,76DownSquareOutlined,77DownloadOutlined,78EditFilled,79EditOutlined,80EllipsisOutlined,81ExclamationCircleFilled,82ExpandOutlined,83ExperimentOutlined,84ExportOutlined,85EyeInvisibleOutlined,86EyeOutlined,87FacebookFilled,88FacebookOutlined,89FieldTimeOutlined,90FileImageOutlined,91FileOutlined,92FilePdfOutlined,93FileTextOutlined,94FileZipOutlined,95FireOutlined,96FolderOpenOutlined,97FolderOutlined,98FontSizeOutlined,99ForkOutlined,100ForwardOutlined,101FrownOutlined,102FunctionOutlined,103FundProjectionScreenOutlined,104GatewayOutlined,105GiftOutlined,106GiftTwoTone,107GithubFilled,108GithubOutlined,109GlobalOutlined,110GoogleOutlined,111GroupOutlined,112HddOutlined,113HighlightOutlined,114HistoryOutlined,115HomeOutlined,116HourglassOutlined,117Html5Outlined,118IdcardOutlined,119InfoCircleOutlined,120InfoOutlined,121InstagramFilled,122InstagramOutlined,123ItalicOutlined,124KeyOutlined,125LaptopOutlined,126LayoutOutlined,127LeftCircleOutlined,128LeftOutlined,129LeftSquareFilled,130LineChartOutlined,131LineHeightOutlined,132LinkOutlined,133LinkedinFilled,134LinkedinOutlined,135LoadingOutlined,136LockFilled,137LockOutlined,138LoginOutlined,139MailOutlined,140MedicineBoxOutlined,141MehOutlined,142MenuOutlined,143MergeCellsOutlined,144MinusCircleOutlined,145MinusOutlined,146MinusSquareOutlined,147OrderedListOutlined,148PauseCircleOutlined,149PercentageOutlined,150PicCenterOutlined,151PlayCircleFilled,152PlayCircleOutlined,153PlaySquareOutlined,154PlusCircleFilled,155PlusCircleOutlined,156PlusOutlined,157PlusSquareOutlined,158PoweroffOutlined,159PrinterOutlined,160ProjectOutlined,161QuestionCircleOutlined,162RedoOutlined,163ReloadOutlined,164RetweetOutlined,165RightCircleFilled,166RightCircleOutlined,167RightOutlined,168RightSquareFilled,169RiseOutlined,170RobotOutlined,171RocketOutlined,172SaveOutlined,173ScissorOutlined,174SearchOutlined,175SelectOutlined,176SendOutlined,177SettingOutlined,178ShareAltOutlined,179ShoppingCartOutlined,180ShrinkOutlined,181SlidersOutlined,182SmileOutlined,183SolutionOutlined,184SoundOutlined,185StarFilled,186StarOutlined,187StepBackwardOutlined,188StepForwardOutlined,189StopFilled,190StopOutlined,191StrikethroughOutlined,192SwapOutlined,193SyncOutlined,194TableOutlined,195TagFilled,196TagOutlined,197TagTwoTone,198TagsFilled,199TagsOutlined,200TagsTwoTone,201TeamOutlined,202ThunderboltOutlined,203ToolOutlined,204TranslationOutlined,205UnderlineOutlined,206UndoOutlined,207UnlockFilled,208UnorderedListOutlined,209UpCircleOutlined,210UpOutlined,211UpSquareOutlined,212UploadOutlined,213UserAddOutlined,214UserDeleteOutlined,215UserOutlined,216UsergroupAddOutlined,217VerticalAlignBottomOutlined,218VerticalAlignMiddleOutlined,219VerticalLeftOutlined,220VerticalRightOutlined,221VideoCameraOutlined,222WalletOutlined,223WarningOutlined,224WifiOutlined,225XOutlined,226YoutubeFilled,227YoutubeOutlined,228} from "@ant-design/icons";229230// Unfortunately -- "error TS7056: The inferred type of this node exceeds the maximum length the231// compiler will serialize. An explicit type annotation is needed."232const IconSpec: { [name: string]: any } = {233"address-card": IdcardOutlined,234aim: AimOutlined,235"align-left": AlignLeftOutlined,236"align-center": AlignCenterOutlined,237"align-justify": { IconFont: "align-justify" },238"align-right": AlignRightOutlined,239"angle-double-left": DoubleLeftOutlined,240"angle-double-right": DoubleRightOutlined,241"angle-down": DownOutlined,242"angle-right": RightOutlined,243"arrow-circle-o-left": { IconFont: "arrowcircleoleft" },244"arrow-circle-down": DownCircleOutlined,245"arrow-circle-up": UpCircleOutlined,246"arrow-down": ArrowDownOutlined,247"arrow-left": ArrowLeftOutlined,248"arrow-right": ArrowRightOutlined,249"arrow-up": ArrowUpOutlined,250atom: { IconFont: "Atom" },251api: ApiOutlined,252audio: AudioOutlined,253aws: { IconFont: "aws" },254backward: BackwardOutlined,255"battery-empty": { IconFont: "battery-empty" },256"battery-quarter": { IconFont: "battery-quarter" },257"battery-half": { IconFont: "battery-half" },258"battery-three-quarters": { IconFont: "battery-three-quarters" },259"battery-full": { IconFont: "battery-full" },260ban: StopOutlined,261bank: BankOutlined,262bars: { IconFont: "bars" },263bell: BellFilled,264"bell-o": BellOutlined,265blog: { IconFont: "blog" },266bold: BoldOutlined,267bolt: ThunderboltOutlined,268book: BookOutlined,269briefcase: { IconFont: "briefcase" },270brush: { IconFont: "brush" },271bullhorn: { IconFont: "bullhorn" },272bug: BugOutlined,273calculator: CalculatorOutlined,274calendar: CalendarOutlined,275"calendar-week": { IconFont: "calendar-week" },276"calendar-check": { IconFont: "calendar-check" },277"calendar-times": { IconFont: "calendar-times" },278camera: CameraOutlined,279"caret-down": CaretDownFilled,280"caret-left": CaretLeftFilled,281"caret-right": CaretRightFilled,282"caret-up": CaretUpFilled,283"caret-square-left": LeftSquareFilled,284"caret-square-right": RightSquareFilled,285"cc-discover": { IconFont: "cc-discover" },286"cc-mastercard": { IconFont: "cc-mastercard" },287"cc-visa": { IconFont: "cc-visa" },288"cc-stripe": { IconFont: "cc-stripe" },289areaChart: AreaChartOutlined,290check: CheckOutlined,291"check-circle": CheckCircleOutlined,292"check-square": CheckSquareOutlined,293"check-square-o": CheckSquareOutlined,294"chevron-down": DownOutlined,295"chevron-left": LeftOutlined,296"chevron-right": RightOutlined,297"chevron-circle-right": RightCircleFilled,298"chevron-up": UpOutlined,299circle: { IconFont: "circle" },300"circle-notch": LoadingOutlined,301clipboard: { IconFont: "clipboard" },302"clipboard-check": { IconFont: "clipboard-check" },303clock: ClockCircleOutlined,304"close-circle-two-tone": CloseCircleTwoTone,305"close-circle-filled": CloseCircleFilled,306clone: { IconFont: "clone" },307cloud: CloudFilled,308"cloud-dev": { IconFont: "cloud-dev" },309"cloud-download": CloudDownloadOutlined,310"cloud-download-alt": CloudDownloadOutlined,311"cloud-upload": CloudUploadOutlined,312"cocalc-ring": { IconFont: "cocalc-ring" },313code: { IconFont: "code" },314"code-outlined": CodeOutlined,315CodeOutlined,316coffee: CoffeeOutlined,317cog: ControlOutlined,318cogs: ControlOutlined,319colors: { IconFont: "colors" },320ColumnHeightOutlined,321ColumnWidthOutlined,322comment: CommentOutlined,323comments: CommentOutlined,324compass: CompassOutlined,325compress: ShrinkOutlined,326copy: CopyOutlined,327"credit-card": CreditCardOutlined,328csv: { IconFont: "csv" },329cube: { IconFont: "cube" },330cut: ScissorOutlined,331dashboard: DashboardOutlined,332database: DatabaseOutlined,333"database-filled": DatabaseFilled,334"deployment-unit": DeploymentUnitOutlined,335dedicated: DatabaseOutlined, // icon for "dedicated resources", looks like a server rack336desktop: DesktopOutlined,337"delivered-procedure-outlined": DeliveredProcedureOutlined,338digitalocean: { IconFont: "digitalocean" },339discord: { IconFont: "discord" },340"disk-drive": { IconFont: "disk-drive" },341"disk-round": { IconFont: "disk-round" },342"disk-snapshot": { IconFont: "disk-snapshot" },343dns: { IconFont: "dns" },344docker: { IconFont: "docker" },345download: DownloadOutlined,346"dot-circle": { IconFont: "dot-circle" },347edit: EditOutlined,348"edit-filled": EditFilled,349eraser: { IconFont: "Eraser-Tool" },350ellipsis: EllipsisOutlined,351envelope: { IconFont: "envelope" },352exchange: { IconFont: "exchange" },353"exclamation-circle": ExclamationCircleFilled,354"exclamation-triangle": WarningOutlined,355expand: ExpandOutlined,356"expand-arrows": ArrowsAltOutlined,357experiment: ExperimentOutlined,358"external-link": { IconFont: "external-link-alt" },359eye: EyeOutlined,360"eye-slash": EyeInvisibleOutlined,361"facebook-filled": FacebookFilled,362facebook: FacebookOutlined,363file: FileOutlined,364"file-archive": FileZipOutlined,365"file-alt": FileTextOutlined,366"file-code": FileTextOutlined,367"file-image": FileImageOutlined,368"file-pdf": FilePdfOutlined,369"file-zip": FileZipOutlined,370files: CopyOutlined,371"file-export": ExportOutlined,372fire: FireOutlined,373firefox: { IconFont: "firefox" },374flash: ThunderboltOutlined,375"flow-chart": { IconFont: "flow-chart" },376folder: FolderOutlined,377"folder-open": FolderOpenOutlined,378font: { IconFont: "font" },379"font-size": FontSizeOutlined,380forward: ForwardOutlined,381frame: { IconFont: "frame" },382frown: FrownOutlined,383fx: FunctionOutlined,384slides: FundProjectionScreenOutlined,385"project-outlined": ProjectOutlined,386"gateway-outlined": GatewayOutlined,387gavel: { IconFont: "gavel" },388gears: ControlOutlined,389gear: ControlOutlined,390gift: GiftOutlined,391gift2: GiftTwoTone,392"github-filled": GithubFilled,393github: GithubOutlined,394git: { IconFont: "git1" },395"git-square": { IconFont: "git-square" },396global: GlobalOutlined,397emacs: { IconFont: "gnuemacs" },398google: GoogleOutlined,399googlecloud: { IconFont: "googlecloud" },400"graduation-cap": { IconFont: "graduation" },401graph: { IconFont: "graph" },402grass: { IconFont: "grass" },403group: { IconFont: "group" },404"group-outlined": GroupOutlined,405gpu: { IconFont: "gpu" },406hand: { IconFont: "hand" },407"hand-stop": PoweroffOutlined,408header: { IconFont: "header" },409heart: { IconFont: "heart" },410hdd: HddOutlined,411highlighter: HighlightOutlined,412history: HistoryOutlined,413home: HomeOutlined,414"horizontal-split": { IconFont: "horizontal-split" },415"hourglass-half": HourglassOutlined,416html5: Html5Outlined,417image: { IconFont: "image" },418icons: { IconFont: "icons" },419"info-circle": InfoCircleOutlined,420indent: { IconFont: "indent" },421info: InfoOutlined,422inkscape: { IconFont: "inkscape" },423"instagram-filled": InstagramFilled,424instagram: InstagramOutlined,425ipynb: { IconFont: "ipynb" },426italic: ItalicOutlined,427"js-square": { IconFont: "js-square" },428julia: { IconFont: "julia" },429jupyter: { IconFont: "ipynb" },430key: KeyOutlined,431keyboard: { IconFont: "keyboard" },432laptop: LaptopOutlined,433layout: LayoutOutlined,434"skull-crossbones": { IconFont: "leave_conference" },435libreoffice: { IconFont: "libreoffice" },436"life-ring": { IconFont: "life-ring" },437"life-saver": { IconFont: "life-ring" },438lightbulb: BulbOutlined,439"line-chart": LineChartOutlined,440link: LinkOutlined,441"linkedin-filled": LinkedinFilled,442linkedin: LinkedinOutlined,443linux: { IconFont: "linux" },444list: UnorderedListOutlined,445"list-ul": UnorderedListOutlined,446"list-alt": UnorderedListOutlined,447"list-ol": OrderedListOutlined,448"lock-open": UnlockFilled,449lock: LockFilled,450"lock-outlined": LockOutlined,451magic: { IconFont: "magic" },452mail: MailOutlined,453map: { IconFont: "map" },454markdown: { IconFont: "markdown" },455mask: { IconFont: "mask" },456maple: { IconFont: "maple" },457mathematica: { IconFont: "mathematica" },458matlab: { IconFont: "matlab" },459medkit: MedicineBoxOutlined,460"menu-outlined": MenuOutlined,461meh: MehOutlined,462microchip: { IconFont: "microchip" },463microsoft: { IconFont: "microsoft" },464"minus-circle": MinusCircleOutlined,465"minus-square": MinusSquareOutlined,466money: CreditCardOutlined,467"money-check": { IconFont: "money-check" },468mousepointer: { IconFont: "mousepointer" },469move: { IconFont: "move" },470arrows: { IconFont: "move" }, // fa-arrows is used by the bqplot custom widget471network: { IconFont: "network" },472"network-server": { IconFont: "network-server" },473"network-wired": ClusterOutlined,474"node-js": { IconFont: "node-js" },475note: { IconFont: "note-text" },476nvidia: { IconFont: "nvidia" },477octave: { IconFont: "octave" },478overview: AppstoreOutlined,479outdent: { IconFont: "outdent" },480pause: PauseCircleOutlined,481"paper-plane": SendOutlined,482paste: { IconFont: "paste" },483"pic-centered": PicCenterOutlined,484pen: { IconFont: "pen" },485pencil: EditOutlined,486"pencil-alt": EditOutlined,487percentage: PercentageOutlined,488play: PlayCircleOutlined,489"play-circle": PlayCircleFilled,490"play-square": PlaySquareOutlined,491plus: PlusOutlined,492minus: MinusOutlined,493"plus-circle": PlusCircleOutlined,494"plus-circle-o": PlusCircleOutlined,495"plus-circle-filled": PlusCircleFilled,496"plus-one": { IconFont: "plus-one" },497"plus-square": PlusSquareOutlined,498"plus-square-o": PlusSquareOutlined,499PoweroffOutlined,500print: PrinterOutlined,501python: { IconFont: "python" },502pytorch: { IconFont: "pytorch" },503qgis: { IconFont: "qgis" },504"question-circle": QuestionCircleOutlined,505"quote-left": { IconFont: "quote-left" },506r: { IconFont: "r" },507racket: { IconFont: "racket" },508redo: RedoOutlined,509refresh: RedoOutlined,510reload: ReloadOutlined,511remove: CloseOutlined,512repeat: RedoOutlined,513replace: { IconFont: "find-replace" },514reply: { IconFont: "reply" },515retweet: RetweetOutlined,516robot: RobotOutlined,517rocket: RocketOutlined,518run: { IconFont: "run" },519sagemath: { IconFont: "sagemath" },520"sagemath-bold": { IconFont: "sagemath-bold" },521"sagemath-file": { IconFont: "sagemath-file" },522save: SaveOutlined,523scheme: { IconFont: "scheme" },524scissors: ScissorOutlined,525search: SearchOutlined,526"search-minus": MinusOutlined, // we actually use this for zoom527"search-plus": PlusOutlined,528"select-outlined": SelectOutlined,529settings: SettingOutlined,530server: CloudServerOutlined,531servers: { IconFont: "servers" },532"sign-in": LoginOutlined,533"sign-out-alt": LoginOutlined, // Yes, since the logout one breaks darkreader, weirdly! they both look reasonable.534sitemap: ClusterOutlined,535"share-square": ShareAltOutlined,536"shopping-cart": ShoppingCartOutlined,537sliders: SlidersOutlined,538smile: SmileOutlined,539"sort-amount-up": { IconFont: "sort-amount-up" },540spinner: { IconFont: "cocalc-ring" },541square: BorderOutlined,542solution: SolutionOutlined,543"square-o": BorderOutlined,544"square-root-alt": { IconFont: "square-root-alt" },545"star-filled": StarFilled,546star: StarOutlined,547"step-backward": StepBackwardOutlined,548"step-forward": StepForwardOutlined,549stop: { IconFont: "stop" }, // the ant-design "stop" looks weird.550"stop-filled": StopFilled,551stopwatch: FieldTimeOutlined,552store: { IconFont: "store" },553strikethrough: StrikethroughOutlined,554subscript: { IconFont: "subscript" },555sun: { IconFont: "sun" },556superscript: { IconFont: "superscript" },557support: { IconFont: "life-ring" },558sync: { IconFont: "sync" },559"sync-alt": SyncOutlined,560tab: { IconFont: "tab" },561table: TableOutlined,562"tachometer-alt": DashboardOutlined,563tasks: { IconFont: "tasks" },564"tag-outlined": TagOutlined,565"tags-outlined": TagsOutlined,566"tag-filled": TagFilled,567"tags-filled": TagsFilled,568"tag-two-tone": TagTwoTone,569"tags-two-tone": TagsTwoTone,570"team-outlined": TeamOutlined,571tensorflow: { IconFont: "tensorflow" },572terminal: CodeOutlined,573tex: { IconFont: "tex" },574text: { IconFont: "text" },575text1: { IconFont: "text1" },576"tex-file": { IconFont: "tex-file" },577"text-height": LineHeightOutlined,578times: CloseOutlined,579"times-circle": CloseCircleOutlined,580"times-rectangle": { IconFont: "times-rectangle" },581"thumbs-down": { IconFont: "thumbs-down" },582"thumbs-up": { IconFont: "thumbs-up" },583"toggle-off": { IconFont: "toggle-off" },584"toggle-on": { IconFont: "toggle-on" },585tool: ToolOutlined,586trash: DeleteOutlined,587"twitter-filled": XOutlined,588twitter: XOutlined,589ubuntu: { IconFont: "ubuntu" },590underline: UnderlineOutlined,591undo: UndoOutlined,592ungroup: { IconFont: "ungroup" },593swap: SwapOutlined,594unlink: { IconFont: "unlink" },595upload: UploadOutlined,596user: UserOutlined,597"user-secret": { IconFont: "user-secret" },598UserAddOutlined,599"user-check": { IconFont: "user-check" },600"user-plus": UsergroupAddOutlined,601"user-slash": { IconFont: "user-slash" },602"user-times": UserDeleteOutlined,603users: UsergroupAddOutlined,604"vertical-split": { IconFont: "vertical-split" },605"vertical-right-outlined": VerticalRightOutlined,606"video-camera": VideoCameraOutlined,607"vertical-align-middle": VerticalAlignMiddleOutlined,608"vertical-align-bottom": VerticalAlignBottomOutlined,609"vertical-left-outlined": VerticalLeftOutlined,610vim: { IconFont: "vim" },611vscode: { IconFont: "vscode" },612wallet: WalletOutlined,613warning: WarningOutlined,614wifi: WifiOutlined,615"window-maximize": { IconFont: "window-maximize" },616"window-restore": DesktopOutlined, // we only use for x11 and this has big X.617wrench: { IconFont: "wrench" },618youtube: YoutubeOutlined,619"youtube-filled": YoutubeFilled,620"left-circle-o": LeftCircleOutlined,621"right-circle-o": RightCircleOutlined,622"down-circle-o": DownCircleOutlined,623"translation-outlined": TranslationOutlined,624"clean-outlined": ClearOutlined,625"sound-outlined": SoundOutlined,626"rise-outlined": RiseOutlined,627"up-square-outlined": UpSquareOutlined,628"down-square-outlined": DownSquareOutlined,629"merge-cells-outlined": MergeCellsOutlined,630"fork-outlined": ForkOutlined,631};632633// Icon Fonts coming from https://www.iconfont.cn/?lang=en-us634import { createFromIconfontCN } from "@ant-design/icons";635export let IconFont: any = undefined;636try {637if (typeof window != "undefined") {638// obviously won't work if window is undefined based on looking at the code...639// This loads a bunch of svg elements of the form <svg id="icon-<name>"... into the DOM.640// The antd Icon code then duplicates these via the <use> html tag641// (https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use)642require("./iconfont.cn");643// note -- we do NOT pass scriptUrl in, as in the docs! Why? Because644// we want everything bundled up into webpack, rather than having to pull645// from some random place, which just causes confusion with releases646// and caching. Fortunately, just evaluating the js from iconfont, then647// running createFromIconfontCN with no arguments does work, as I deduced648// by reading the code, then trying this.649// https://github.com/ant-design/ant-design-icons/blob/5be2afd296636ab4cfec5d3a2793d6cd41b1789b/packages/icons-vue/src/components/IconFont.tsx650651IconFont = createFromIconfontCN();652653// It would be easy to screw up and put an entry like654// "arrow-circle-o-left": { IconFont: "arrowcircleoleft" }655// in IconSpec, but forget to actually include "arrowcircleoleft" in656// iconfont.cn, or -- just as bad -- make a typo or put the wrong name in.657// So we double check that all iconfonts are actually defined here:658if (typeof DEBUG != "undefined" && DEBUG) {659setTimeout(() => {660// only do this during dev to save time.661for (const name in IconSpec) {662const spec = IconSpec[name];663const x = spec?.IconFont;664if (x != null) {665const id = `icon-${x}`;666if (document.getElementById(id) == null) {667console.error(668`ERROR -- the IconFont ${x} is not in components/iconfont.cn! Fix this or the icon ${name} will be broken.`,669);670}671}672}673}, 5000);674}675}676} catch (err) {677// Might as well have option for a graceful fallback, e.g., when678// used from node.js...679console.log(`IconFont not available -- ${err}`);680}681682// This was nice but unfortunately it exceeds typescript limits.683//export type IconName = keyof typeof IconSpec;684export type IconName = string;685export const IconName = undefined; // Javascript needs this, though we are only using IconName for the type686687// Typeguard so can tell if a string is name of an icon and also688// make typescript happy.689export function isIconName(name?: string): name is IconName {690if (name == null) return false;691return IconSpec[name] != null;692}693694export const iconNames: IconName[] = Object.keys(IconSpec) as any;695696export type IconRotation = "45" | "90" | "135" | "180" | "225" | "270" | "315";697698interface Props {699name?: IconName;700unicode?: number; // (optional) set a hex 16 bit charcode to render a unicode char, e.g. 0x2620701className?: string;702size?: "lg" | "2x" | "3x" | "4x" | "5x";703rotate?: IconRotation;704flip?: "horizontal" | "vertical";705spin?: boolean;706pulse?: boolean;707stack?: "1x" | "2x";708inverse?: boolean;709style?: CSS;710onClick?: (event?: React.MouseEvent) => void; // https://fettblog.eu/typescript-react/events/711onMouseOver?: () => void;712onMouseOut?: () => void;713onMouseEnter?: () => void;714onMouseLeave?: () => void;715}716717const UNICODE_STYLE = {718fontSize: "120%",719fontWeight: "bold",720lineHeight: "1",721verticalAlign: "middle",722} as React.CSSProperties;723724const missing: any = {};725// Converted from https://github.com/andreypopp/react-fa726727export const Icon: React.FC<Props> = (props: Props) => {728// IMPORTANT: This hook is needed for next.js to support server side rendering.729// Otherwise, at least with next 13, it crashes when rendering icons.730const onFrontend = useOnFrontend();731if (!onFrontend) return null;732733if (props.unicode != null) {734return (735<span style={{ ...UNICODE_STYLE, ...props.style }}>736{String.fromCharCode(props.unicode!)}737</span>738);739}740741let name: IconName = props.name ?? "square";742let C;743C = IconSpec[name];744if (C == null && name.endsWith("-o")) {745// should be impossible because of typescript...746// try without -o747C = IconSpec[name.slice(0, name.length - 2)];748}749if (C != null) {750if (typeof C.IconFont == "string") {751// @ts-ignore752if (IconFont == null) {753return <span>(IconFonts not available)</span>;754}755return <IconFont type={"icon-" + C.IconFont} {...props} alt={name} />;756}757return <C {...props} alt={name} />;758}759760// this is when the icon is broken.761if (typeof DEBUG != "undefined" && DEBUG) {762if (missing[props.name ?? ""] == null) {763missing[props.name ?? ""] = true;764console.warn(765`Icon "${props.name}" is not defined -- fix this in components/icon.tsx.`,766);767}768// make it hopefully clear to devs that this icon is broken769return (770<span771style={{ background: "red", color: "white" }}772className="blink"773title={`Icon "${props.name}" is not defined -- fix this in components/icon.tsx.`}774>775{/* @ts-ignore */}776<BugOutlined {...props} alt={name} />777</span>778);779} else {780// In production, just show a very generic icon so the user781// doesn't realize we messed up.782// @ts-ignore783return <BorderOutlined {...props} alt={name} />;784}785};786787// TOOD move this to a shared lib, which can import the IconName type788export const PAYASYOUGO_ICON: IconName = "compass";789790791