import React, { forwardRef, useContext, HTMLAttributes } from "react";
import classNames from "classnames";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { library, FlipProp } from "@fortawesome/fontawesome-svg-core";
// far
import { faFileAlt } from "@fortawesome/free-regular-svg-icons/faFileAlt";
import { faQuestionCircle as faQuestionCircleRegular } from "@fortawesome/free-regular-svg-icons/faQuestionCircle";
import { faUser as faUserRegular } from "@fortawesome/free-regular-svg-icons/faUser";
import { faCheckCircle as faCheckCircleRegular } from "@fortawesome/free-regular-svg-icons/faCheckCircle";
import { faTimesCircle } from "@fortawesome/free-regular-svg-icons/faTimesCircle";
import { faClock } from "@fortawesome/free-regular-svg-icons/faClock";
import { faKeyboard } from "@fortawesome/free-regular-svg-icons/faKeyboard";
import { faStar } from "@fortawesome/free-regular-svg-icons/faStar";
import { faThumbsDown } from "@fortawesome/free-regular-svg-icons/faThumbsDown";
import { faThumbsUp } from "@fortawesome/free-regular-svg-icons/faThumbsUp";
// fas
import { faArchive } from "@fortawesome/free-solid-svg-icons/faArchive";
import { faArrowDown } from "@fortawesome/free-solid-svg-icons/faArrowDown";
import { faArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowLeft";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons/faArrowRight";
import { faArrowUp } from "@fortawesome/free-solid-svg-icons/faArrowUp";
import { faBackward } from "@fortawesome/free-solid-svg-icons/faBackward";
import { faBan } from "@fortawesome/free-solid-svg-icons/faBan";
import { faBolt } from "@fortawesome/free-solid-svg-icons/faBolt";
import { faCalculator } from "@fortawesome/free-solid-svg-icons/faCalculator";
import { faCalendar } from "@fortawesome/free-solid-svg-icons/faCalendar";
import { faCaretDown } from "@fortawesome/free-solid-svg-icons/faCaretDown";
import { faCaretUp } from "@fortawesome/free-solid-svg-icons/faCaretUp";
import { faCheck } from "@fortawesome/free-solid-svg-icons/faCheck";
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle";
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
import { faChevronLeft } from "@fortawesome/free-solid-svg-icons/faChevronLeft";
import { faChevronRight } from "@fortawesome/free-solid-svg-icons/faChevronRight";
import { faChevronUp } from "@fortawesome/free-solid-svg-icons/faChevronUp";
import { faCircle } from "@fortawesome/free-solid-svg-icons/faCircle";
import { faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch";
import { faClipboard } from "@fortawesome/free-solid-svg-icons/faClipboard";
import { faCog } from "@fortawesome/free-solid-svg-icons/faCog";
import { faColumns } from "@fortawesome/free-solid-svg-icons/faColumns";
import { faCommentAlt } from "@fortawesome/free-solid-svg-icons/faCommentAlt";
import { faCompress } from "@fortawesome/free-solid-svg-icons/faCompress";
import { faEllipsisH } from "@fortawesome/free-solid-svg-icons/faEllipsisH";
import { faEllipsisV } from "@fortawesome/free-solid-svg-icons/faEllipsisV";
import { faEnvelope } from "@fortawesome/free-solid-svg-icons/faEnvelope";
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons/faExclamationTriangle";
import { faExpand } from "@fortawesome/free-solid-svg-icons/faExpand";
import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons/faExternalLinkAlt";
import { faExternalLinkSquareAlt } from "@fortawesome/free-solid-svg-icons/faExternalLinkSquareAlt";
import { faEye } from "@fortawesome/free-solid-svg-icons/faEye";
import { faEyeSlash } from "@fortawesome/free-solid-svg-icons/faEyeSlash";
import { faFastBackward } from "@fortawesome/free-solid-svg-icons/faFastBackward";
import { faFastForward } from "@fortawesome/free-solid-svg-icons/faFastForward";
import { faFileAlt as faFileAltSolid } from "@fortawesome/free-solid-svg-icons/faFileAlt";
import { faFileImport } from "@fortawesome/free-solid-svg-icons/faFileImport";
import { faFileSignature } from "@fortawesome/free-solid-svg-icons/faFileSignature";
import { faFilter } from "@fortawesome/free-solid-svg-icons/faFilter";
import { faFlag } from "@fortawesome/free-solid-svg-icons/faFlag";
import { faFolder } from "@fortawesome/free-solid-svg-icons/faFolder";
import { faForward } from "@fortawesome/free-solid-svg-icons/faForward";
import { faGripLines } from "@fortawesome/free-solid-svg-icons/faGripLines";
import { faGripLinesVertical } from "@fortawesome/free-solid-svg-icons/faGripLinesVertical";
import { faHashtag } from "@fortawesome/free-solid-svg-icons/faHashtag";
import { faInfoCircle } from "@fortawesome/free-solid-svg-icons/faInfoCircle";
import { faKey } from "@fortawesome/free-solid-svg-icons/faKey";
import { faLayerGroup } from "@fortawesome/free-solid-svg-icons/faLayerGroup";
import { faLevelUpAlt } from "@fortawesome/free-solid-svg-icons/faLevelUpAlt";
import { faListUl } from "@fortawesome/free-solid-svg-icons/faListUl";
import { faLock } from "@fortawesome/free-solid-svg-icons/faLock";
import { faLongArrowAltRight } from "@fortawesome/free-solid-svg-icons/faLongArrowAltRight";
import { faMagic } from "@fortawesome/free-solid-svg-icons/faMagic";
import { faMapSigns } from "@fortawesome/free-solid-svg-icons/faMapSigns";
import { faMinus } from "@fortawesome/free-solid-svg-icons/faMinus";
import { faPaperclip } from "@fortawesome/free-solid-svg-icons/faPaperclip";
import { faPause } from "@fortawesome/free-solid-svg-icons/faPause";
import { faPen } from "@fortawesome/free-solid-svg-icons/faPen";
import { faPlay } from "@fortawesome/free-solid-svg-icons/faPlay";
import { faPlus } from "@fortawesome/free-solid-svg-icons/faPlus";
import { faPlusCircle } from "@fortawesome/free-solid-svg-icons/faPlusCircle";
import { faPooStorm } from "@fortawesome/free-solid-svg-icons/faPooStorm";
import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons/faQuestionCircle";
import { faScroll } from "@fortawesome/free-solid-svg-icons/faScroll";
import { faSearch } from "@fortawesome/free-solid-svg-icons/faSearch";
import { faShieldAlt } from "@fortawesome/free-solid-svg-icons/faShieldAlt";
import { faSlidersH } from "@fortawesome/free-solid-svg-icons/faSlidersH";
import { faSort } from "@fortawesome/free-solid-svg-icons/faSort";
import { faSortDown } from "@fortawesome/free-solid-svg-icons/faSortDown";
import { faSortUp } from "@fortawesome/free-solid-svg-icons/faSortUp";
import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner";
import { faSquare } from "@fortawesome/free-solid-svg-icons/faSquare";
import { faStar as faStarSolid } from "@fortawesome/free-solid-svg-icons/faStar";
import { faSync } from "@fortawesome/free-solid-svg-icons/faSync";
import { faTasks } from "@fortawesome/free-solid-svg-icons/faTasks";
import { faThLarge } from "@fortawesome/free-solid-svg-icons/faThLarge";
import { faTicketAlt } from "@fortawesome/free-solid-svg-icons/faTicketAlt";
import { faTimes } from "@fortawesome/free-solid-svg-icons/faTimes";
import { faTrash } from "@fortawesome/free-solid-svg-icons/faTrash";
import { faUser } from "@fortawesome/free-solid-svg-icons/faUser";
import { faUserAstronaut } from "@fortawesome/free-solid-svg-icons/faUserAstronaut";
import { faUserPlus } from "@fortawesome/free-solid-svg-icons/faUserPlus";
import { faUsers } from "@fortawesome/free-solid-svg-icons/faUsers";
import { faUserFriends } from "@fortawesome/free-solid-svg-icons/faUserFriends";
// Custom icon SVGs
import { DialogCheck, Scroll, Sparkle, TriangleDown, TriangleUp } from "./svg";
import { StatusContext } from "../../contexts/status";
import { STATUS_VARIANT } from "../../types";
import { bemHOF } from "../../utilities";
import { SvgProps } from "../Svg";
const cn = bemHOF("Icon");
library.add(
faArchive,
faArrowDown,
faArrowLeft,
faArrowRight,
faArrowUp,
faBackward,
faBan,
faBolt,
faCalculator,
faCalendar,
faCaretDown,
faCaretUp,
faCheck,
faCheckCircle,
faCheckCircleRegular,
faChevronDown,
faChevronLeft,
faChevronRight,
faChevronUp,
faCircle,
faCircleNotch,
faClipboard,
faClock,
faCog,
faColumns,
faCommentAlt,
faCompress,
faEllipsisH,
faEllipsisV,
faEnvelope,
faExclamationTriangle,
faExpand,
faExternalLinkAlt,
faExternalLinkSquareAlt,
faEye,
faEyeSlash,
faFastBackward,
faFastForward,
faFileAlt,
faFileAltSolid,
faFileImport,
faFileSignature,
faFilter,
faFlag,
faFolder,
faForward,
faGripLines,
faGripLinesVertical,
faHashtag,
faInfoCircle,
faKey,
faKeyboard,
faLayerGroup,
faLevelUpAlt,
faListUl,
faLock,
faLongArrowAltRight,
faMagic,
faMapSigns,
faMinus,
faPaperclip,
faPause,
faPen,
faPlay,
faPlus,
faPlusCircle,
faPooStorm,
faQuestionCircle,
faQuestionCircleRegular,
faScroll,
faSearch,
faShieldAlt,
faSlidersH,
faSort,
faSortDown,
faSortUp,
faSpinner,
faSquare,
faStar,
faStarSolid,
faSync,
faTasks,
faThLarge,
faThumbsDown,
faThumbsUp,
faTicketAlt,
faTimes,
faTimesCircle,
faTrash,
faUser,
faUserAstronaut,
faUserPlus,
faUserRegular,
faUsers,
faUserFriends,
);
export enum CUSTOM_ICON_TYPE {
DIALOG_CHECK = "dialog-check",
SCROLL = "scroll",
SPARKLE = "sparkle",
TRIANGLE_DOWN = "triangle-down",
TRIANGLE_UP = "triangle-up",
}
type CustomIconPaths = Record<
CUSTOM_ICON_TYPE,
(props: SvgProps) => JSX.Element
>;
const CustomIcons: CustomIconPaths = {
[CUSTOM_ICON_TYPE.DIALOG_CHECK]: DialogCheck,
[CUSTOM_ICON_TYPE.SCROLL]: Scroll,
[CUSTOM_ICON_TYPE.SPARKLE]: Sparkle,
[CUSTOM_ICON_TYPE.TRIANGLE_DOWN]: TriangleDown,
[CUSTOM_ICON_TYPE.TRIANGLE_UP]: TriangleUp,
};
export enum ICON_TYPE {
ARCHIVE = "archive",
ARROW_DOWN = "arrow-down",
ARROW_LEFT = "arrow-left",
ARROW_RIGHT = "arrow-right",
ARROW_UP = "arrow-up",
BACKWARD = "backward",
BAN = "ban",
BOLT = "bolt",
CALENDAR = "calendar",
CALCULATOR = "calculator",
CARET_DOWN = "caret-down",
CARET_UP = "caret-up",
CHECK = "check",
CHECK_CIRCLE = "check-circle",
CHEVRON_DOWN = "chevron-down",
CHEVRON_LEFT = "chevron-left",
CHEVRON_RIGHT = "chevron-right",
CHEVRON_UP = "chevron-up",
CIRCLE = "circle",
CIRCLE_NOTCH = "circle-notch",
CLOCK = "clock",
CLIPBOARD = "clipboard",
COG = "cog",
COLUMNS = "columns",
COMMENT_ALT = "comment-alt",
COMPRESS = "compress",
ELLIPSIS_H = "ellipsis-h",
ELLIPSIS_V = "ellipsis-v",
ENVELOPE = "envelope",
EXCLAMATION_TRIANGLE = "exclamation-triangle",
EXPAND = "expand",
EXTERNAL_LINK_ALT = "external-link-alt",
EXTERNAL_LINK_SQUARE_ALT = "external-link-square-alt",
EYE = "eye",
EYE_SLASH = "eye-slash",
FAST_BACKWARD = "fast-backward",
FAST_FORWARD = "fast-forward",
FILE_ALT = "file-alt",
FILE_IMPORT = "file-import",
FILE_SIGNATURE = "file-signature",
FILTER = "filter",
FLAG = "flag",
FOLDER = "folder",
FORWARD = "forward",
GRIP_LINES = "grip-lines",
GRIP_LINES_VERTICAL = "grip-lines-vertical",
HASHTAG = "hashtag",
INFO_CIRCLE = "info-circle",
KEY = "key",
KEYBOARD = "keyboard",
LAYER_GROUP = "layer-group",
LEVEL_UP_ALT = "level-up-alt",
LIST_UL = "list-ul",
LOCK = "lock",
LONG_ARROW_ALT_RIGHT = "long-arrow-alt-right",
MAGIC = "magic",
MAP_SIGNS = "map-signs",
MINUS = "minus",
PAPERCLIP = "paperclip",
PAUSE = "pause",
PEN = "pen",
PLAY = "play",
PLUS = "plus",
PLUS_CIRCLE = "plus-circle",
POO_STORM = "poo-storm", // Use in storybook examples
QUESTION_CIRCLE = "question-circle",
SCROLL = "scroll",
SEARCH = "search",
SHIELD_ALT = "shield-alt",
SLIDERS_H = "sliders-h",
SORT = "sort",
SORT_DOWN = "sort-down",
SORT_UP = "sort-up",
SPINNER = "spinner",
SQUARE = "square",
STAR = "star",
SYNC = "sync",
TASKS = "tasks",
TICKET_ALT = "ticket-alt",
TIMES = "times",
TIMES_CIRCLE = "times-circle",
TH_LARGE = "th-large",
THUMBS_DOWN = "thumbs-down",
THUMBS_UP = "thumbs-up",
TRASH = "trash",
USER = "user",
USER_ASTRONAUT = "user-astronaut",
USER_PLUS = "user-plus",
USERS = "users",
USER_FRIENDS = "user-friends",
}
export enum ICON_STYLE_PREFIX {
SOLID = "fas",
REGULAR = "far",
}
interface BaseIconProps extends HTMLAttributes {
color?: string;
[key: string]: any; // Until comply is on typescript v4, this is needed to allow for data-testid attribute
}
export interface SharedFaIconProps extends BaseIconProps {
spin?: boolean;
prefix?: ICON_STYLE_PREFIX;
flip?: FlipProp;
}
export interface FaIconProps extends SharedFaIconProps {
icon: ICON_TYPE;
}
export interface CustomIconProps extends BaseIconProps {
icon: CUSTOM_ICON_TYPE;
}
export type IconProps = FaIconProps | CustomIconProps;
export interface StatusIconProps extends SharedFaIconProps {
status?: STATUS_VARIANT;
}
const getIconClasses = ({
className,
color,
}: Pick) =>
classNames("inline-flex", className, color ? `text-${color}` : "");
export const Icon = forwardRef((props, ref) => {
const isCustomIcon = Object.values(CUSTOM_ICON_TYPE).some(
(i) => i === props.icon,
);
if (isCustomIcon) {
const { style, className, color, icon, ...rest } = props as CustomIconProps;
const CustomIcon = CustomIcons[icon];
return (
);
}
const {
icon,
style,
className,
spin = false,
color,
prefix: prefixProp,
flip,
...rest
} = props as FaIconProps;
/** If no value is provided to the prefix prop, icons will revert to
* default "fas" (solid) prefix unless otherwise set in this object.
*
* regular === "far"
* */
const iconSetDefaults: { [key in ICON_TYPE]?: ICON_STYLE_PREFIX } = {
[ICON_TYPE.FILE_ALT]: ICON_STYLE_PREFIX.REGULAR,
[ICON_TYPE.TIMES_CIRCLE]: ICON_STYLE_PREFIX.REGULAR,
[ICON_TYPE.CLOCK]: ICON_STYLE_PREFIX.REGULAR,
[ICON_TYPE.KEYBOARD]: ICON_STYLE_PREFIX.REGULAR,
[ICON_TYPE.STAR]: ICON_STYLE_PREFIX.REGULAR,
[ICON_TYPE.THUMBS_DOWN]: ICON_STYLE_PREFIX.REGULAR,
[ICON_TYPE.THUMBS_UP]: ICON_STYLE_PREFIX.REGULAR,
};
const prefix: ICON_STYLE_PREFIX =
prefixProp || iconSetDefaults[icon] || ICON_STYLE_PREFIX.SOLID;
const faIcon: [ICON_STYLE_PREFIX, ICON_TYPE] = [prefix, icon];
return (
);
});
export const StatusIcon = forwardRef(
({ status: statusProp, ...rest }, ref) => {
const context = useContext(StatusContext);
let computedStatus = STATUS_VARIANT.DEFAULT;
if (statusProp) {
computedStatus = statusProp;
} else if (context) {
computedStatus = context;
}
let icon = ICON_TYPE.INFO_CIRCLE;
switch (computedStatus) {
case STATUS_VARIANT.SUCCESS:
icon = ICON_TYPE.CHECK;
break;
case STATUS_VARIANT.WARNING:
icon = ICON_TYPE.EXCLAMATION_TRIANGLE;
break;
case STATUS_VARIANT.DANGER:
icon = ICON_TYPE.BAN;
break;
default:
break;
}
return ;
},
);