// // All icons are imported from https://fontawesome.com/icons?d=gallery // Icons are under the license https://fontawesome.com/license // // Note: when adding new icons, review https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/RTL_Guidelines // to determine whether or not the icons should be mirrored in right-to-left languages. import React from "react"; import oc from "open-color"; import clsx from "clsx"; import { Theme } from "../element/types"; import { THEME } from "../constants"; const iconFillColor = (theme: Theme) => "var(--icon-fill-color)"; const handlerColor = (theme: Theme) => theme === THEME.LIGHT ? oc.white : "#1e1e1e"; type Opts = { width?: number; height?: number; mirror?: true; } & React.SVGProps; export const createIcon = ( d: string | React.ReactNode, opts: number | Opts = 512, ) => { const { width = 512, height = width, mirror, style, ...rest } = typeof opts === "number" ? ({ width: opts } as Opts) : opts; return ( ); }; const tablerIconProps: Opts = { width: 24, height: 24, fill: "none", strokeWidth: 2, stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", } as const; const modifiedTablerIconProps: Opts = { width: 20, height: 20, fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", } as const; // ----------------------------------------------------------------------------- // tabler-icons: present export const PlusPromoIcon = createIcon( , tablerIconProps, ); // tabler-icons: book export const LibraryIcon = createIcon( , tablerIconProps, ); // tabler-icons: plus export const PlusIcon = createIcon( , tablerIconProps, ); // tabler-icons: dots-vertical export const DotsIcon = createIcon( , tablerIconProps, ); // tabler-icons: pinned export const PinIcon = createIcon( , tablerIconProps, ); // tabler-icons: lock-open (via Figma) export const UnlockedIcon = createIcon( , modifiedTablerIconProps, ); // tabler-icons: lock (via Figma) export const LockedIcon = createIcon( , modifiedTablerIconProps, ); // custom export const WelcomeScreenMenuArrow = createIcon( <> , { width: 41, height: 94, fill: "none" }, ); // custom export const WelcomeScreenHelpArrow = createIcon( <> , { width: 85, height: 71, fill: "none" }, ); // custom export const WelcomeScreenTopToolbarArrow = createIcon( <> , { width: 38, height: 78, fill: "none" }, ); // custom export const ExcalLogo = createIcon( , { width: 26, height: 62, fill: "none" }, ); // custom export const SelectionIcon = createIcon( , { fill: "none", width: 22, height: 22, strokeWidth: 1.25 }, ); // tabler-icons: square export const RectangleIcon = createIcon( , tablerIconProps, ); // tabler-icons: square-rotated export const DiamondIcon = createIcon( , tablerIconProps, ); // tabler-icons: circle export const EllipseIcon = createIcon( , tablerIconProps, ); // tabler-icons: arrow-narrow-right export const ArrowIcon = createIcon( , tablerIconProps, ); // custom? export const LineIcon = createIcon( , modifiedTablerIconProps, ); export const PenModeIcon = createIcon( , tablerIconProps, ); // modified tabler-icons: pencil export const FreedrawIcon = createIcon( , modifiedTablerIconProps, ); // tabler-icons: typography export const TextIcon = createIcon( , tablerIconProps, ); // modified tabler-icons: photo export const ImageIcon = createIcon( , modifiedTablerIconProps, ); // tabler-icons: eraser export const EraserIcon = createIcon( , tablerIconProps, ); export const ZoomInIcon = createIcon( , modifiedTablerIconProps, ); export const ZoomOutIcon = createIcon( , modifiedTablerIconProps, ); export const TrashIcon = createIcon( , modifiedTablerIconProps, ); export const DuplicateIcon = createIcon( , modifiedTablerIconProps, ); export const MoonIcon = createIcon( , modifiedTablerIconProps, ); export const SunIcon = createIcon( , modifiedTablerIconProps, ); export const HamburgerMenuIcon = createIcon( , tablerIconProps, ); export const ExportIcon = createIcon( , modifiedTablerIconProps, ); export const HelpIcon = createIcon( , tablerIconProps, ); export const ExternalLinkIcon = createIcon( , modifiedTablerIconProps, ); export const GithubIcon = createIcon( , modifiedTablerIconProps, ); export const DiscordIcon = createIcon( , modifiedTablerIconProps, ); export const TwitterIcon = createIcon( , tablerIconProps, ); export const checkIcon = createIcon( , { width: 24, height: 24, }, ); export const LinkIcon = createIcon( , modifiedTablerIconProps, ); export const save = createIcon( "M433.941 129.941l-83.882-83.882A48 48 0 0 0 316.118 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V163.882a48 48 0 0 0-14.059-33.941zM224 416c-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64zm96-304.52V212c0 6.627-5.373 12-12 12H76c-6.627 0-12-5.373-12-12V108c0-6.627 5.373-12 12-12h228.52c3.183 0 6.235 1.264 8.485 3.515l3.48 3.48A11.996 11.996 0 0 1 320 111.48z", { width: 448, height: 512 }, ); export const saveAs = createIcon( "M252 54L203 8a28 27 0 00-20-8H28C12 0 0 12 0 27v195c0 15 12 26 28 26h204c15 0 28-11 28-26V73a28 27 0 00-8-19zM130 213c-21 0-37-16-37-36 0-19 16-35 37-35 20 0 37 16 37 35 0 20-17 36-37 36zm56-169v56c0 4-4 6-7 6H44c-4 0-7-2-7-6V42c0-4 3-7 7-7h133l4 2 3 2a7 7 0 012 5z M296 201l87 95-188 205-78 9c-10 1-19-8-18-20l9-84zm141-14l-41-44a31 31 0 00-46 0l-38 41 87 95 38-42c13-14 13-36 0-50z", { width: 448, height: 512 }, ); // tabler-icon: folder export const LoadIcon = createIcon( , modifiedTablerIconProps, ); export const clipboard = createIcon( "M384 112v352c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h80c0-35.29 28.71-64 64-64s64 28.71 64 64h80c26.51 0 48 21.49 48 48zM192 40c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24m96 114v-20a6 6 0 0 0-6-6H102a6 6 0 0 0-6 6v20a6 6 0 0 0 6 6h180a6 6 0 0 0 6-6z", { width: 384, height: 512 }, ); export const palette = createIcon( "M204.3 5C104.9 24.4 24.8 104.3 5.2 203.4c-37 187 131.7 326.4 258.8 306.7 41.2-6.4 61.4-54.6 42.5-91.7-23.1-45.4 9.9-98.4 60.9-98.4h79.7c35.8 0 64.8-29.6 64.9-65.3C511.5 97.1 368.1-26.9 204.3 5zM96 320c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm32-128c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128-64c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128 64c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z", ); export const ExportImageIcon = createIcon( , tablerIconProps, ); export const exportToFileIcon = createIcon( "M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z", { width: 512, height: 512 }, ); export const zoomIn = createIcon( "M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z", { width: 448, height: 512 }, ); export const zoomOut = createIcon( "M416 208H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h384c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z", { width: 448, height: 512 }, ); export const done = createIcon( "M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z", ); export const menu = createIcon( "M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z", ); export const UndoIcon = createIcon( , modifiedTablerIconProps, ); export const RedoIcon = createIcon( , modifiedTablerIconProps, ); export const questionCircle = createIcon( "M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z", { mirror: true }, ); export const share = createIcon( , modifiedTablerIconProps, ); export const shareIOS = createIcon( "M16 5l-1.42 1.42-1.59-1.59V16h-1.98V4.83L9.42 6.42 8 5l4-4 4 4zm4 5v11c0 1.1-.9 2-2 2H6c-1.11 0-2-.9-2-2V10c0-1.11.89-2 2-2h3v2H6v11h12V10h-3V8h3c1.1 0 2 .89 2 2z", { width: 24, height: 24 }, ); export const shareWindows = createIcon( <> , { width: 64, height: 64 }, ); // Icon imported form Storybook // Storybook is licensed under MIT https://github.com/storybookjs/storybook/blob/next/LICENSE export const resetZoom = createIcon( , { width: 1024 }, ); export const BringForwardIcon = createIcon( <> , modifiedTablerIconProps, ); export const SendBackwardIcon = createIcon( <> , modifiedTablerIconProps, ); export const BringToFrontIcon = createIcon( <> , modifiedTablerIconProps, ); export const SendToBackIcon = createIcon( <> , modifiedTablerIconProps, ); // // Align action icons created from scratch to match those of z-index actions // Note: vertical align icons are flipped so the larger item is always the // first one the user sees. Horizontal align icons should not be flipped since // that would make them lie about their function. // export const AlignTopIcon = createIcon( <> , modifiedTablerIconProps, ); export const AlignBottomIcon = createIcon( <> , modifiedTablerIconProps, ); export const AlignLeftIcon = createIcon( <> , modifiedTablerIconProps, ); export const AlignRightIcon = createIcon( <> , modifiedTablerIconProps, ); export const DistributeHorizontallyIcon = createIcon( <> , modifiedTablerIconProps, ); export const DistributeVerticallyIcon = createIcon( <> , modifiedTablerIconProps, ); export const CenterVerticallyIcon = createIcon( , modifiedTablerIconProps, ); export const CenterHorizontallyIcon = createIcon( , modifiedTablerIconProps, ); export const UsersIcon = createIcon( , tablerIconProps, ); // not mirrored because it's inspired by a playback control, which is always RTL export const start = createIcon( "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm115.7 272l-176 101c-15.8 8.8-35.7-2.5-35.7-21V152c0-18.4 19.8-29.8 35.7-21l176 107c16.4 9.2 16.4 32.9 0 42z", ); export const stop = createIcon( "M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm96 328c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h160c8.8 0 16 7.2 16 16v160z", ); export const CloseIcon = createIcon( <> , modifiedTablerIconProps, ); export const back = createIcon( "M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z", { width: 320, height: 512, style: { marginLeft: "-0.2rem" }, mirror: true }, ); export const clone = createIcon( "M464 0c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48H176c-26.51 0-48-21.49-48-48V48c0-26.51 21.49-48 48-48h288M176 416c-44.112 0-80-35.888-80-80V128H48c-26.51 0-48 21.49-48 48v288c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48v-48H176z", { mirror: true }, ); // modified https://feathericons.com/?query=shield export const shield = createIcon( "M11.553 22.894a.998.998 0 00.894 0s3.037-1.516 5.465-4.097C19.616 16.987 21 14.663 21 12V5a1 1 0 00-.649-.936l-8-3a.998.998 0 00-.702 0l-8 3A1 1 0 003 5v7c0 2.663 1.384 4.987 3.088 6.797 2.428 2.581 5.465 4.097 5.465 4.097zm-1.303-8.481l6.644-6.644a.856.856 0 111.212 1.212l-7.25 7.25a.856.856 0 01-1.212 0l-3.75-3.75a.856.856 0 111.212-1.212l3.144 3.144z", { width: 24 }, ); export const file = createIcon( "M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm32-48h224V288l-23.5-23.5c-4.7-4.7-12.3-4.7-17 0L176 352l-39.5-39.5c-4.7-4.7-12.3-4.7-17 0L80 352v64zm48-240c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z", { width: 384, height: 512 }, ); // TODO barnabasmolnar/editor-redesign // couldn't find a new icon for this export const GroupIcon = React.memo(({ theme }: { theme: Theme }) => createIcon( <> , { width: 182, height: 182, mirror: true }, ), ); export const UngroupIcon = React.memo(({ theme }: { theme: Theme }) => createIcon( <> , { width: 182, height: 182, mirror: true }, ), ); export const FillHachureIcon = createIcon( <> , modifiedTablerIconProps, ); export const FillCrossHatchIcon = createIcon( <> , modifiedTablerIconProps, ); export const FillSolidIcon = createIcon( <> , { ...modifiedTablerIconProps, fill: "currentColor" }, ); export const StrokeWidthBaseIcon = createIcon( <> , modifiedTablerIconProps, ); export const StrokeWidthBoldIcon = createIcon( , modifiedTablerIconProps, ); export const StrokeWidthExtraBoldIcon = createIcon( , modifiedTablerIconProps, ); export const StrokeStyleSolidIcon = React.memo(({ theme }: { theme: Theme }) => createIcon( , { width: 40, height: 20, }, ), ); export const StrokeStyleDashedIcon = createIcon( , tablerIconProps, ); // tabler-icons: line-dotted export const StrokeStyleDottedIcon = createIcon( , tablerIconProps, ); export const SloppinessArchitectIcon = createIcon( , modifiedTablerIconProps, ); export const SloppinessArtistIcon = createIcon( , modifiedTablerIconProps, ); export const SloppinessCartoonistIcon = createIcon( , modifiedTablerIconProps, ); export const EdgeSharpIcon = createIcon( , modifiedTablerIconProps, ); // tabler-icons: border-radius export const EdgeRoundIcon = createIcon( , tablerIconProps, ); export const ArrowheadNoneIcon = createIcon( , { width: 40, height: 20, }, ); export const ArrowheadArrowIcon = React.memo( ({ flip = false }: { flip?: boolean }) => createIcon( , { width: 40, height: 20 }, ), ); export const ArrowheadDotIcon = React.memo( ({ flip = false }: { flip?: boolean }) => createIcon( , { width: 40, height: 20 }, ), ); export const ArrowheadBarIcon = React.memo( ({ flip = false }: { flip?: boolean }) => createIcon( , { width: 40, height: 20 }, ), ); export const ArrowheadTriangleIcon = React.memo( ({ flip = false }: { flip?: boolean }) => createIcon( , { width: 40, height: 20 }, ), ); export const FontSizeSmallIcon = createIcon( <> , modifiedTablerIconProps, ); export const FontSizeMediumIcon = createIcon( <> , modifiedTablerIconProps, ); export const FontSizeLargeIcon = createIcon( <> , modifiedTablerIconProps, ); export const FontSizeExtraLargeIcon = createIcon( <> , modifiedTablerIconProps, ); export const FontFamilyNormalIcon = createIcon( <> , modifiedTablerIconProps, ); export const FontFamilyCodeIcon = createIcon( <> , modifiedTablerIconProps, ); export const TextAlignLeftIcon = createIcon( , tablerIconProps, ); export const TextAlignCenterIcon = createIcon( , tablerIconProps, ); export const TextAlignRightIcon = createIcon( , tablerIconProps, ); // tabler-icons: layout-align-top export const TextAlignTopIcon = React.memo(({ theme }: { theme: Theme }) => createIcon( , tablerIconProps, ), ); // tabler-icons: layout-align-bottom export const TextAlignBottomIcon = React.memo(({ theme }: { theme: Theme }) => createIcon( , tablerIconProps, ), ); // tabler-icons: layout-align-middle export const TextAlignMiddleIcon = React.memo(({ theme }: { theme: Theme }) => createIcon( , tablerIconProps, ), ); export const publishIcon = createIcon( , { width: 640, height: 512 }, ); export const eraser = createIcon( , );