mirror of
https://github.com/outline/outline.git
synced 2025-12-20 10:09:43 -06:00
584 lines
12 KiB
TypeScript
584 lines
12 KiB
TypeScript
import {
|
|
faApple,
|
|
faWindows,
|
|
faAndroid,
|
|
faSquareJs,
|
|
faPython,
|
|
faWebAwesome,
|
|
faXTwitter,
|
|
faBluesky,
|
|
} from "@fortawesome/free-brands-svg-icons";
|
|
import {
|
|
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,
|
|
faGamepad,
|
|
faGauge,
|
|
faGem,
|
|
faGift,
|
|
faHammer,
|
|
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,
|
|
faWheelchairMove,
|
|
faWorm,
|
|
faYenSign,
|
|
faHandsClapping,
|
|
faFolderClosed,
|
|
faFlaskVial,
|
|
} from "@fortawesome/free-solid-svg-icons";
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
import intersection from "lodash/intersection";
|
|
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;
|
|
};
|
|
|
|
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,
|
|
].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;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: ${(props) => props.size}px;
|
|
height: ${(props) => props.size}px;
|
|
`;
|